diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..185c511 Binary files /dev/null and b/.DS_Store differ diff --git a/SoundDrivers/AD1816.ASM b/SoundDrivers/AD1816.ASM new file mode 100755 index 0000000..0f10386 --- /dev/null +++ b/SoundDrivers/AD1816.ASM @@ -0,0 +1,2116 @@ +; +; Analog Device's AD1816 +; + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;********************************** + +PNPSERIALID EQU 0FFFFFFFFh +PNPVENDORID EQU 80719304h + +STEREOENABLED EQU 1 +DMABUFFERLENGTH EQU 8192 +MIXRESOLUTION EQU 32 ; 32 bit mixing for +MIXTABLESIZE EQU 2*256*65 + +Debug DW 0 +Debug2 DW 0 +DMASize DW 2048 + +ESSMsg DB "SoundPort AD1816 found", 13 + DB "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, DMA ", 0FDh, "D", 0 + +ESSNoMemoryMsg DB "SoundPort AD1816 found", 13 + DB "Error: Insufficient memory", 0 + +ReinitMsg DB "SoundPort AD1816 reinitialised", 0 + +DriverName DB "ITAD1816.DRV", 0 + +Forced DB 0 +Stereo DB 0 +MixVolume DW 0 + +BytesToMix DW 1000 +ESSMixConst DB 0 + +MixSegment DW 0 +DMASegment DW 0 + +MixTransferOffset DW 0 +MixTransferRemaining DW 0 + +CONFIGURATIONOFFSET EQU $+128 +CONFIGSIZE EQU 6 +MixMode DW 0 +MixModeOffset DW 0 +Filter DW 0 + +IMR DW 0 +OldESSIRQHandler DD 0 + +FilterValue DD 0 +FilterValue2 DD 0 + +IRQData Label Word + DW 20h, 1111111111111110b ; IRQ 0 + DW 24h, 1111111111111101b ; IRQ 1 + DW 28h, 1111110111111011b ; IRQ 2 + DW 2Ch, 1111111111110111b ; IRQ 3 + DW 30h, 1111111111101111b ; IRQ 4 + DW 34h, 1111111111011111b ; IRQ 5 + DW 38h, 1111111110111111b ; IRQ 6 + DW 3Ch, 1111111101111111b ; IRQ 7 + DW 1C0h, 1111111011111011b ; IRQ 8 + DW 1C4h, 1111110111111011b ; IRQ 9 + DW 1C8h, 1111101111111011b ; IRQ 10 + DW 1CCh, 1111011111111011b ; IRQ 11 + DW 1D0h, 1110111111111011b ; IRQ 12 + DW 1D4h, 1101111111111011b ; IRQ 13 + DW 1D8h, 1011111111111011b ; IRQ 14 + DW 1DCh, 0111111111111011b ; IRQ 15 + +ESSScreenList Label + DW 16 + DW Near Ptr IdleFunctionList + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr ESSHeaderLine + + DW Near Ptr DriverText + + DW Near Ptr MixModeText + DW Near Ptr MixModeButton1 ; 6 + DW Near Ptr MixModeButton2 ; + DW Near Ptr MixModeButton3 ; 8 + DW Near Ptr MixModeButton4 ; 9 + + DW Near Ptr FilterText + DW Near Ptr FilterButton1 ; 11 + DW Near Ptr FilterButton2 + DW Near Ptr FilterButton3 + + DW Near Ptr VolumeText + DW Near Ptr VolumeBox1 + + DW Near Ptr MasterVolumeLeft ; 16 + DW Near Ptr MasterVolumeRight ; 17 + DW Near Ptr PhatStereo ; 18 + + DW Near Ptr DebugText + DW Near Ptr DebugText2 + + DW 0 + +ESSHeaderLine DW 10 + DB "SoundPort AD1816 Driver", 0 + +EmptyObject DW 1 + DB 0, 0 + DB 0 + DB 0 + +DriverText DW 1 + DB 31, 48 + DB 21h + DB "SoundPort AD1816 Driver 1.0 for Impulse Tracker", 0 + +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +IdleFunctionList DD 0 + DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +VolumeText DW 1 + DB 2, 14 + DB 20h + DB "Master Volume Left", 13 + DB "Master Volume Right", 13 + DB "3D Phat Stereo", 13 + DB 0 + +VolumeBox1 DW 0 + DB 21, 13, 39, 17 + DB 25 + +PhatStereo DW 14 + DB 22, 16 + DW 0, 15 + DW 9, 2 + DW 17, 6, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 16 + +MasterVolumeLeft DW 14 + DB 22, 14 + DW 0, 63 + DW 9, 0 + DW 0FFFFh, 17, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 16 + +MasterVolumeRight DW 14 + DB 22, 15 + DW 0, 63 + DW 9, 1 + DW 16, 18, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 16 + +MixModeText DW 1 + DB 2, 18 + DB 20h + DB "Mixing Mode, Playback Frequency: ", 0FDh, "DHz", 0 +MixSpeed DW 44100 + +MixModeButton1 DW 2 + DW 18, 7, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment1 DW 0 + DW 0 + DW Offset SetMixMode +DriverSegment2 DW 0 + DB 3, 20, 32, 22, 8 + DB 0 + DB " 16 Bit, Non-Interpolated", 0 + +MixModeButton2 DW 2 + DW 6, 8, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment3 DW 0 + DW 2 + DW Offset SetMixMode +DriverSegment4 DW 0 + DB 3, 23, 32, 25, 8 + DB 0 + DB " 16 Bit, Interpolated", 0 + +MixModeButton3 DW 2 + DW 7, 9, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment5 DW 0 + DW 4 + DW Offset SetMixMode +DriverSegment6 DW 0 + DB 3, 26, 32, 28, 8 + DB 0 + DB " 32 Bit, Non-Interpolated", 0 + +MixModeButton4 DW 2 + DW 8, 11, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment7 DW 0 + DW 6 + DW Offset SetMixMode +DriverSegment8 DW 0 + DB 3, 29, 32, 31, 8 + DB 0 + DB " 32 Bit, Interpolated", 0 + +FilterText DW 1 + DB 2, 33 + DB 20h + DB "Filter mode", 0 + +FilterButton1 DW 2 + DW 9, 12, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment9 DW 0 + DW 0 + DW Offset SetFilter +DriverSegment10 DW 0 + DB 3, 35, 29, 37, 8 + DB 0 + DB " No Filter", 0 + +FilterButton2 DW 2 + DW 11, 13, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment11 DW 0 + DW 1 + DW Offset SetFilter +DriverSegment12 DW 0 + DB 3, 38, 29, 40, 8 + DB 0 + DB " 50% Filter", 0 + +FilterButton3 DW 2 + DW 12, 0FFFFh, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment13 DW 0 + DW 2 + DW Offset SetFilter +DriverSegment14 DW 0 + DB 3, 41, 29, 43, 8 + DB 0 + DB " 75% Filter", 0 + +DebugText DW 1 + DB 2, 47 + DB 20h + DB "MIDI Port: ", 0FDh, "Xh", 0 +MIDIPort DW 0 + +DebugText2 DW 1 + DB 2, 48 + DB 20h + DB "MIDI IRQ: ", 0FDh, "Dh", 0 +MIDIIRQ DW 0 + +VolumeTable DB 56, 56, 0 + +; ÄÄ MixingRoutines ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixBufferPos DW 0 + +include dmasirq.inc +include mix.inc +include m12bit.mix +include m12biti.mix +include m32bit.mix +include m32biti.mix + +MixFunctionTables Label + +include m12bit.inc ; contains the tables +include m12biti.inc +include m32bit.inc +include m32biti.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +RelocationTable Label Word + DW Offset DriverSegment1, Offset DriverSegment2 + DW Offset DriverSegment3, Offset DriverSegment4 + DW Offset DriverSegment5, Offset DriverSegment6 + DW Offset DriverSegment7, Offset DriverSegment8 + DW Offset DriverSegment9, Offset DriverSegment10 + DW Offset DriverSegment11, Offset DriverSegment12 + DW Offset DriverSegment13, Offset DriverSegment14 + DW 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc AD1816Wait + + PushA + Xor CX, CX + Mov DX, CS:BasePort + +AD1816Wait1: + In AL, DX + Test AL, 80h + LoopZ AD1816Wait1 + + PopA + Ret + +EndP AD1816Wait + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc AD1816RegisterOut ; AL = indirect register, BX = contents + + Call AD1816Wait + + Push DX + PushF + + ClI + + Mov DX, CS:BasePort + Out DX, AL + Add DL, 2 + + Mov AL, BL + Out DX, AL + Inc DX + Mov AL, BH + Out DX, AL + + PopF + Pop DX + + Ret + +EndP AD1816RegisterOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc AD1816RegisterIn ; AL = register + ; Returns BX + + Call AD1816Wait + + Push AX + Push DX + + Mov DX, CS:BasePort + Out DX, AL + Add DL, 2 + + In AL, DX + Mov BL, AL + Inc DX + In AL, DX + Mov BH, AL + + Pop DX + Pop AX + + Ret + +EndP AD1816RegisterIn + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixMode Far + + Push CS + Pop ES + Mov DI, Offset MixMode + + Ret + +EndP GetMixMode + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetFilter Far + + Push CS + Pop ES + Mov DI, Offset Filter + + Ret + +EndP GetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetFilter Far + + Mov AX, [SI+22] + Mov CS:FilterValue, 0 + Mov CS:Filter, AX + + Mov AX, 1 + Ret + +EndP SetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixMode Far + + Mov AX, [SI+22] + + ClI + + Mov CS:MixMode, AX + + Mov BX, 180 + Mul BX + Mov CS:MixModeOffset, AX + + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS:RecalculateAllVolumes + + StI + + Mov AX, 1 + Ret + +EndP SetMixMode + Assume DS:Nothing + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +PnP_SerialID DD 0 +PnP_VendorID DD 0 +PnP_ReadPort DW 0 +PnP_CSN DB 0 +PnP_CardFound DB 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_Delay + Assume DS:Driver + + Push AX CX + + Mov CX, 180h +PnP_Delay1: + In AL, 21h + Loop PnP_Delay1 + + Pop CX AX + Ret + +EndP PnP_Delay + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_WriteData + + Mov DX, 279h + Out DX, AL + + Mov AL, AH + Mov DH, 0Ah + Out DX, AL + Ret + +EndP PnP_WriteData + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_ReadData + + Mov DX, 279h + Out DX, AL + + Mov DX, PnP_ReadPort + In AL, DX + + Ret + +EndP PnP_ReadData + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_Isolate + + Mov AX, 402h + Call Pnp_WriteData ; Reset CSNs + +PnP_IsolateNextCard: + Mov AX, 0003h + Call PnP_WriteData ; Wake[0] + + Mov AX, PnP_ReadPort + ShL AX, 6 + Xor AL, AL + Call PnP_WriteData ; Set Read Data port. + + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + + Mov AL, 1 ; Serial Isolation + Mov DX, 279h + Out DX, AL + + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + + Mov BL, 6Ah + Mov CX, 64 + Mov DX, PnP_ReadPort + + ClI + +PnP_Isolate1: + ShR PnP_SerialID, 1 + RCR PnP_VendorID, 1 + + Mov BH, BL + ShR BH, 1 + Xor BH, BL + ShR BX, 1 + + In AL, DX + Mov AH, AL + Call PnP_Delay + In AL, DX + Call PnP_Delay + + Cmp AX, 55AAh + JNE PnP_Isolate2 + + Xor BL, 80h + Or PnP_SerialID, 80000000h + +PnP_Isolate2: + Dec CX + JNZ PnP_Isolate1 + + Mov CX, 8 + Xor BH, BH + +PnP_Isolate3: + ShR BH, 1 + + In AL, DX + Mov AH, AL + Call PnP_Delay + In AL, DX + Call PnP_Delay + Cmp AX, 55AAh + JNE PnP_Isolate4 + + Or BH, 80h + +PnP_Isolate4: + Dec CX + JNZ PnP_Isolate3 + + StI + + Cmp BL, BH ; Matching Checksum? + JNE PnP_IsolateFinished + + ; assign CSN + Inc PnP_CSN + + Mov AL, 6 + MOv AH, PnP_CSN + Call PnP_WriteData + + Cmp PnP_VendorID, PNPVENDORID + JNE PnP_IsolateNextCard + Cmp PnP_SerialID, PNPSERIALID + JNE PnP_IsolateNextCard + + Mov AL, 3 + Call PnP_WriteData + Mov AX, 007h + Call PnP_WriteData + + Mov AL, 64h + Call PnP_ReadData + Mov AH, AL + Mov AL, 65h + Call PnP_ReadData ; AX = address. + Cmp BasePort, 0FFFFh + JE PnPBasePortOK + + Cmp BasePort, AX + JNE PnP_IsolateNextCard + +PnPBasePortOK: + Mov BasePort, AX + + Mov AL, 70h + Call PnP_ReadData ; AL[3:0] = IRQ + And AX, 15 + JZ PnP_IsolateNextCard + Mov IRQ, AX + + Mov AL, 74h + Call PnP_ReadData ; AL[2:0] = DMA + And AX, 7 + Cmp AL, 4 + JE PnP_IsolateNextCard + Mov DMA, AX + + Mov CX, 107h + +MIDISearchLoop: + Mov AX, CX + Call PnP_WriteData + + Mov AL, 60h + Call PnP_ReadData + Mov AH, AL + Mov AL, 61h + Call PnP_ReadData ; AX = address. + + Test AX, 0Fh + JNZ NextMIDI + Cmp AX, 300h + JB NextMIDI + Cmp AX, 400h + JAE NextMIDI + + Mov MIDIPort, AX + + Mov AL, 70h + Call PnP_ReadData ; AL[3:0] = IRQ + And AX, 15 + Mov MIDIIRQ, AX + + Mov Pnp_CardFound, 1 + Jmp PnP_IsolateNextCard + +NextMIDI: + Add CX, 100h + Cmp CX, 0F07h + JBE MIDISearchLoop + +PnP_IsolateFinished: + Mov AL, PnP_CSN + ShL AL, 1 + Or AL, PnP_CardFound + + Ret + +EndP PnP_Isolate + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far ; returns carry clear if succesful + + Push CS + Pop DS + + Xor AL, AL + Mov DX, 279h + Out DX, AL + Out DX, AL + + Mov AL, 6Ah ; Starting value + Mov CX, 32 + +PnP_InitiationKeyLoop: + Out DX, AL + + Mov AH, AL + ShR AH, 1 + Xor AH, AL + ShR AX, 1 + + Dec CX + JNZ PnP_InitiationKeyLoop + +; Try three ports before concluding no PnP cards: 20Fh, 27Bh, 213h + +PnP_DetectCardPort1: + Mov PnP_ReadPort, 20Fh + Call PnP_Isolate + JZ PnP_DetectCardPort2 + Test AL, 1 + JZ PnP_DetectCardNotFound + Jmp PnP_DetectCardFound + +PnP_DetectCardPort2: + Mov PnP_ReadPort, 27Bh + Call PnP_Isolate + JZ PnP_DetectCardPort3 + Test AL, 1 + JZ PnP_DetectCardNotFound + Jmp PnP_DetectCardFound + +PnP_DetectCardPort3: + Mov PnP_ReadPort, 213h + Call PnP_Isolate + Test AL, 1 + JNZ PnP_DetectCardFound + +PnP_DetectCardNotFound: + StC + Jmp PnP_DetectEnd + +PnP_DetectCardFound: + ClC + +PnP_DetectEnd: ; Return PnP to wait for key state + Mov AX, 202h + Call PnP_WriteData + Mov EAX, 'Jeff' + + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixModeTable Label Word + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + +Proc MixSamples ; Given DS:SI = info tables, CX = numchannels + + ; 1. Clean buffer + ; + update variables + ; 2. Update parameters + ; 3. Mix func + ; 4. Return + + Push CX + + Mov CX, BytesToMix + Mov ES, MixSegment + Mov DI, MIXTABLESIZE + Xor EAX, EAX + Mov DX, CX + Add CX, CX + + Mov MixTransferOffset, DI ; } Memory write + + Cmp Stereo, 0 + JE MixSamples1 + + Mov DX, CX + +MixSamples1: + Rep StosD ; } Memory write + Mov MixTransferRemaining, DX ; } + + Pop CX + +MixSamples2: + Test Byte Ptr [SI], 1 + JZ MixSamplesEnd2 + Cmp Byte Ptr [SI+36h], 100 + JE MixSamplesEnd2 + + Push CX + Mov CX, [SI] + + Test CH, 2 + JZ MixSamples3 + And Byte Ptr [SI], Not 1 + + Jmp MixSamplesEnd +; Cmp MixMode, 8 ; Is it volume ramping? +; JB MixSamplesEnd + +MixSamples3: + Test CL, 20h ; New freq? + JZ MixSamples5 + + Mov AX, [SI+10h] + Mov DX, [SI+12h] + Mov BX, MixSpeed + Cmp DX, BX + JAE MixSamplesHandleError + + Div BX + ShL EAX, 16 + Xor AX, AX + Div BX + Mov STEPVALUE, EAX + +MixSamples4: + Test CH, 1 + JZ MixSamples5 + + Mov DWord Ptr [SI+1Ch], 0 ; Current Volume = 0 + ; for volume sliding. +MixSamples5: + Test CX, 8440h ; New volume or panning? + JZ MixSamplesMix + + Xor AX, AX + Test CH, 8 ; Muted? + JNZ MixModeCommon + + Mov BX, MixMode + Add BL, Stereo + Add BX, BX + Jmp [CS:MixModeTable+BX] + +Mix0Mode: ; 16-bit mixing, no interpolation +Mix0ModeMono: ; and 16-bit mixing, interpolation + Mov AL, [SI+20h] + ShR AL, 1 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 30 ; Use left only-mixing for mono + Jmp MixModeCommon + +Mix0ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix0ModeSurround + + Mul Byte Ptr [SI+20h] ; Final volume + Add AX, 64 + ShR AX, 7 + Mov [SI+0Ch], AX ; Store into right volume + + Mov AL, 64 + Sub AL, [SI+37h] + Mul Byte Ptr [SI+20h] + Add AX, 64 + ShR AX, 7 + Mov [SI+0Eh], AX ; Left volume + + Mov CH, AL ; CH = left volume + Mov CL, [SI+0Ch] ; CL = right volume + Mov AX, 0 + + Test CX, CX + JZ MixModeCommon + + Mov AL, 30 ; Left only... + Test CL, CL + JZ MixModeCommon + + Mov AL, 60 + Test CH, CH + JZ MixModeCommon + + Mov AL, 90 + Cmp CL, CH + JZ MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix0ModeSurround: + Mov AL, [SI+20h] + ShR AL, 2 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 150 ; Surround + Jmp MixModeCommon + +Mix6ModeMono: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 8 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Test AX, AX + JZ MixModeCommon + Mov AX, 30 + Jmp MixModeCommon + +Mix6ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix6ModeSurround + + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Ch], AX ; Store into right volume + Mov BX, AX + ShL EAX, 16 + + Mov AL, 64 ; Do left volume + Sub AL, [SI+37h] ; AL = 64-FinalPan + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Eh], AX + + Mov ECX, EAX + + ; BX = right volume + ; CX = Left volume + Mov AX, 0 + Test ECX, ECX + JZ MixModeCommon + + Mov AL, 30 + Test BX, BX + JZ MixModeCommon + + Mov AL, 60 + Test CX, CX + JZ MixModeCommon + + Mov AL, 90 + Cmp CX, BX + JE MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix6ModeSurround: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 9 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + JZ MixModeCommon + Mov AX, 150 + Jmp MixModeCommon + +MixModeCommon: ; Requires AX = 30/60/90 etc. depending + ; On mixing mode type. + ; This will add 180 for 16-bit, + ; And sort out loop types. + Mov BL, [SI+0Ah] + Test Byte Ptr [SI+18h], 2 ; 16 bit? + JZ MixModeCommon1 + + Add AX, 180 + +MixModeCommon1: + Cmp BL, 8 + JB MixModeCommon3 ; No loop + JE MixModeCommon2 ; Forwards loop + + Add AX, 10 + +MixModeCommon2: + Add AX, 10 + +MixModeCommon3: + Add AX, Offset MixFunctionTables + Add AX, MixModeOffset + Mov [SI+8], AX ; Offset... + +MixSamplesMix: + Mov BX, [SI+8] ; BX = offset into + Mov EAX, [CS:BX+2] + Mov DWord Ptr PreMixFunction, EAX + Mov EAX, [CS:BX+6] + Mov DWord Ptr MixFunctionSeparateBackwards, EAX + + Mov AX, BytesToMix + Mov MixBlockSize, AX + Mov MixBufferOffset, MIXTABLESIZE + + Mov EAX, CURRENTPOSITION + Mov OLDPOSITION, EAX + + Call Word Ptr [CS:BX] + + And Word Ptr [SI], 0111100010001101b + Jmp MixSamplesEnd + +MixSamplesHandleError: + Mov Word Ptr [SI], 200h + + Test Byte Ptr [SI+3Ah], 80h + JNZ MixSamplesEnd + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Turn off channel + +MixSamplesEnd: + Pop CX + +MixSamplesEnd2: + Add SI, 128 + Dec CX + JNZ MixSamples2 + + Ret + +EndP MixSamples + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ESSIRQHandler + + PushAD + Push DS + Push ES + + ClD + + Mov AX, CS + Mov DS, AX + Assume DS:Driver + + Mov DX, [BasePort] + Inc Debug + + Inc DX + In AL, DX + Mov AH, AL + Xor AL, AL + Out DX, AL +; Call AD1816Out + + Mov AL, 20h + Cmp IRQ, 8 + JB WSSAckIRQ1 + + Out 0A0h, AL + +WSSAckIRQ1: + Out 20h, AL + + Mov AX, MixBufferPos + Mov BX, AX + Mul DMASize + Cmp AX, DMABUFFERLENGTH + JB ESSIRQHandler2 + + Xor AX, AX + Xor BX, BX + +ESSIRQHandler2: + Inc BX + Mov MixBufferPos, BX + + CLD + + + ; OK... time to get next block + ; Check whether stereo thing is on.. + ; + LES DI, [ActualDMAPtr] + Add DI, AX + + Mov BX, DMASize ; BX = bytes required + ShR BX, 1 + ; BX = samples required + Mov BP, 8 ; Skip for mono + Mov CL, 14 ; Shift for mono + + Cmp Stereo, 0 + JE ESSIRQHandlerMono + + Mov BP, 4 ; Stereo skip value. + Dec CL + +ESSIRQHandlerMono: + Call SaveEMSPageFrame + + Cmp MixTransferRemaining, 0 + JNE ESSIRQHandler4 + Assume DS:Nothing + +ESSIRQHandler3: + Push BX + Push CX + Push BP + Push ES + Push DI + + Call Update + Call MixSamples + + Pop DI + Pop ES + Pop BP + Pop CX + Pop BX + +ESSIRQHandler4: + Mov DS, MixSegment + Mov SI, MixTransferOffset + Mov DX, BX ; DX = samples to transfer + Cmp DX, MixTransferRemaining + JBE ESSIRQHandler5 + + Mov DX, MixTransferRemaining + +ESSIRQHandler5: + Push DX + Cmp CS:Filter, 1 + JB ESSIRQHandler6 + JE ESSIRQHFilter + + Cmp CS:Stereo, 0 + JE ESSIRQ3QFilterMono + +ESSIRQ3QFilterStereo: + Push BX + + Mov EBX, FilterValue + Mov EBP, FilterValue2 + ShR DX, 1 + +ESSIRQ3QFilterStereo1: + Mov EAX, EBX + Mov ECX, EBP + Add EAX, [SI] + Add ECX, [SI+4] + SAR EAX, 1 + SAR ECX, 1 + Add EBX, EAX + Add EBP, ECX + SAR EBX, 1 + SAR EBP, 1 + + Mov EAX, EBX + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSS3QFilterStereoClip1 + Cmp EAX, 7FFFh + JG WSS3QFilterStereoClip2 + +ESSIRQ3QFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSS3QFilterStereoClip3 + Cmp EAX, 7FFFh + JG WSS3QFilterStereoClip4 + +ESSIRQ3QFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ ESSIRQ3QFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp WSSMixTransferEnd + +ESSIRQ3QFilterMono: + Push BX + + Mov EBX, FilterValue + +ESSIRQ3QFilterMono1: + Mov EAX, EBX + Add EAX, [SI] + SAR EAX, 1 + Add EBX, EAX + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL WSS3QFilterMonoClip1 + Cmp EAX, 7FFFh + JG WSS3QFilterMonoClip2 + +ESSIRQ3QFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ ESSIRQ3QFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp WSSMixTransferEnd + +ESSIRQHFilter: + Cmp CS:Stereo, 0 + JE ESSIRQHFilterMono + +ESSIRQHFilterStereo: + Push BX + + Mov EBX, FilterValue + Mov EBP, FilterValue2 + ShR DX, 1 + +ESSIRQHFilterStereo1: + Add EBX, [SI] + Add EBP, [SI+4] + + SAR EBX, 1 + SAR EBP, 1 + + Mov EAX, EBX + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSSHFilterStereoClip1 + Cmp EAX, 7FFFh + JG WSSHFilterStereoClip2 + +ESSIRQHFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSSHFilterStereoClip3 + Cmp EAX, 7FFFh + JG WSSHFilterStereoClip4 + +ESSIRQHFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ ESSIRQHFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp WSSMixTransferEnd + +ESSIRQHFilterMono: + Push BX + + Mov EBX, FilterValue + +ESSIRQHFilterMono1: + Add EBX, [SI] + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL WSSHFilterMonoClip1 + Cmp EAX, 7FFFh + JG WSSHFilterMonoClip2 + +ESSIRQHFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ ESSIRQHFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp WSSMixTransferEnd + +ESSIRQHandler6: + Mov EAX, [SI] + SAR EAX, CL + + Cmp EAX, -8000h + JL ESSIRQHandlerClip1 + Cmp EAX, 7FFFh + JG ESSIRQHandlerClip2 + +ESSIRQHandler7: + StosW ; } Memory write + + Add SI, BP + Dec DX + JNZ ESSIRQHandler6 + +WSSMixTransferEnd: + Pop DX + + Sub MixTransferRemaining, DX ; } Memory write + Sub BX, DX + JNZ ESSIRQHandler3 + + Mov MixTransferOffset, SI ; } Memory write + + Call RestoreEMSPageFrame + + Pop ES + Pop DS + PopAD + IRet + +ESSIRQHandlerClip1: + Mov AX, 8000h + Jmp ESSIRQHandler7 + +ESSIRQHandlerClip2: + Mov AX, 7FFFh + Jmp ESSIRQHandler7 + +WSSHFilterMonoClip1: + Mov AX, 8000h + Jmp ESSIRQHFilterMono2 + +WSSHFilterMonoClip2: + Mov AX, 7FFFh + Jmp ESSIRQHFilterMono2 + +WSSHFilterStereoClip1: + Mov AX, 8000h + Jmp ESSIRQHFilterStereo2 + +WSSHFilterStereoClip2: + Mov AX, 7FFFh + Jmp ESSIRQHFilterStereo2 + +WSSHFilterStereoClip3: + Mov AX, 8000h + Jmp ESSIRQHFilterStereo3 + +WSSHFilterStereoClip4: + Mov AX, 7FFFh + Jmp ESSIRQHFilterStereo3 + +WSS3QFilterMonoClip1: + Mov AX, 8000h + Jmp ESSIRQ3QFilterMono2 + +WSS3QFilterMonoClip2: + Mov AX, 7FFFh + Jmp ESSIRQ3QFilterMono2 + +WSS3QFilterStereoClip1: + Mov AX, 8000h + Jmp ESSIRQ3QFilterStereo2 + +WSS3QFilterStereoClip2: + Mov AX, 7FFFh + Jmp ESSIRQ3QFilterStereo2 + +WSS3QFilterStereoClip3: + Mov AX, 8000h + Jmp ESSIRQ3QFilterStereo3 + +WSS3QFilterStereoClip4: + Mov AX, 7FFFh + Jmp ESSIRQ3QFilterStereo3 + +EndP ESSIRQHandler + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Add DI, Offset IRQData + Mov BX, [CS:DI] + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset ESSIRQHandler + + XChg [ES:BX], EAX + Mov OldESSIRQHandler, EAX + + Mov AX, IMR + And AX, [DI+2] + + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Pop ES + PopAD + + Ret + +EndP SetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Mov BX, [IRQData+DI] + + Mov EAX, OldESSIRQHandler + Mov [ES:BX], EAX + + Pop ES + PopAD + + Ret + +EndP ResetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StopAD1816 + + PushA + + Mov AL, 1 + Call AD1816RegisterIn + And BX, 07FFFh ; Disable PIE + Call AD1816RegisterOut + + Mov DX, CS:BasePort + Inc DX + In AL, DX + And AL, Not 80h + Out DX, AL + + Add DL, 7 + In AL, DX + And AL, Not 1 + Out DX, AL + + PopA + Ret + +EndP StopAD1816 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StartAD1816 + + PushA + Push ES + Push DS + + Push CS + Pop DS + Assume DS:Driver + + ; Setup DMA + Mov BX, DMASegment + Xor AX, AX + Mov DX, DMA + Mov DI, DMABUFFERLENGTH + Call SetDMA + + LES DI, ActualDMAPtr + Xor AX, AX + Mov CX, DMABUFFERLENGTH/2 + Rep StosW + + Mov MixBufferPos, 0 + Mov MixTransferRemaining, 0 + + Mov AL, 4 + Call AD1816RegisterIn + + Mov AL, 32 + Call AD1816RegisterIn + Or BX, 08000h + Call AD1816RegisterOut + + Mov AL, 2 ; Sample rate + Mov BX, MixSpeed + Call AD1816RegisterOut + + Mov AL, 8 ; DMA Size + Mov BX, DMASize + ShR BX, 2 + Dec BX + Call AD1816RegisterOut + + Mov DX, BasePort ; Wave Format + Add DL, 8 + + Mov AL, 00010001b + Cmp Stereo, 0 + JE StartAD1816A + + Or AL, 4 + +StartAD1816A: + Out DX, AL + + Mov AL, 1 ; Enable Playback interrupt + Call AD1816RegisterIn + Or BX, 8000h + Call AD1816RegisterOut + + Pop DS + Pop ES + PopA + + Ret + +EndP StartAD1816 + Assume DS:Nothing + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov SI, Offset RelocationTable + +RelocationFix: + LodsW + Test AX, AX + JZ RelocationEnd + Mov BX, AX + Mov [BX], DS + Jmp RelocationFix + + +RelocationEnd: + Call GetEMSPageFrame + Mov EMSPageFrame, AX + + In AL, 0A1h + Mov AH, AL + In AL, 21h + Mov IMR, AX + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + Mov AX, CmdLineMixSpeed + Test AX, AX + JZ ClipMixSpeed3 + + Cmp AX, 11050 + JA ClipMixSpeed1 + + Mov AX, 11050 + +ClipMixSpeed1: + Cmp AX, 55200 + JB ClipMixSpeed2 + + Mov AX, 55200 + +ClipMixSpeed2: + Mov MixSpeed, AX + +ClipMixSpeed3: + Mov AX, 2643 + Mul MixSpeed + Add AX, 0FFFFh + AdC DX, 2080 + + Mov BX, (DMABUFFERLENGTH*2)/16 + Add BX, DX + + ; Allocate MixSegment first + Mov AH, 48h + + Int 21h + JNC InitSound1 + +InitSoundNoMemory: + Mov SI, Offset ESSNoMemoryMsg + Ret + +InitSound1: + Mov MixSegment, AX + Add AX, DX + Mov DMASegment, AX + + Call SetIRQ + Call GetTempo + Call SetTempo + + Call UpdateSoundcardVariables + + Mov SI, Offset ESSMsg + + Mov AX, BasePort + Mov BX, IRQ + Mov CX, DMA + + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Call ResetIRQ + Call SetIRQ + + Mov SI, Offset ReInitMsg + Mov BX, 40 + Call SetInfoLine + + Mov AL, Stereo + Call SetStereo + + Pop ES + Pop DS + PopA + + Ret + +EndP ReInitSound + Assume DS:Nothing + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, IMR + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Mov AX, MixSegment + Test AX, AX + JZ UnInitSound1 + + Push AX + + Call StopAD1816 + Call ResetIRQ + + Pop ES + Mov AH, 49h ; Release MixSegment + Int 21h + + +UnInitSound1: + Call GotoHomeDirectory + + ; Now to save config into driver file. + Mov AX, 3D02h ; Read write access + Mov DX, Offset DriverName + Int 21h + JC SetMixMode1 + + Mov BX, AX + + Mov AX, 4200h + Xor CX, CX + Mov DX, Offset CONFIGURATIONOFFSET + Int 21h + JC SetMixMode2 + + Mov AH, 40h + Mov CX, CONFIGSIZE + Mov DX, Offset MixMode + Int 21h + +SetMixMode2: + Mov AH, 3Eh + Int 21h + +SetMixMode1: + Ret + +EndP UnInitSound + Assume DS:Nothing + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + +DMAPort1 EQU $+1 + In AL, 1 + Mov BL, AL + +DMAPort2 EQU $+1 + In AL, 1 + Mov BH, AL + + Mov CS:Debug2, BX + + Ret + +EndP Poll + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Push AX + Push BX + Push DX + + Push BX + + Mov AX, MixSpeed + Mov BX, AX + Xor DX, DX + + ShL AX, 1 + RCL DX, 1 ; DX:AX = Mixspeed*2 + + ShR BX, 1 ; BX = Mixspeed/2 + + Add AX, BX + AdC DX, 0 ; DX:AX = Mixspeed*2.5 + + Pop BX ; BX = tempo + Div BX + + Mov BytesToMix, AX + + Pop DX + Pop BX + Pop AX + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + PushA + Push DS + + Mov BX, AX ; BX = MixVolume + Mov CS:MixVolume, BX + + Mov AX, CS:MixSegment + Test AX, AX + JZ SetMixVolume2 + + Mov DS, AX + + Mov CX, MIXTABLESIZE/2 + Mov SI, MIXTABLESIZE-2; Starting point - working backwards + +SetMixVolume1: + Mov AX, CX + + Dec AX ; AH = volume, AL = wave value. + Xor DX, DX + XChg AH, DL ; DL = Volume, AX = wave value + CBW + + IMul DX ; DX:AX = Volume * Wave Value + ; Ranges -8192->8128 + + IMul BX ; DX:AX = Volume * Wave Value * Mixing Volume + ; Ranges -1048576->1040384 + + Add AX, 64 + AdC DX, 0 + + ShRD AX, DX, 7 + Mov [SI], AX + Sub SI, 2 + + Loop SetMixVolume1 + +SetMixVolume2: + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS:RecalculateAllVolumes + + Pop DS + PopA + + Ret + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Mov CS:Stereo, AL + Cmp CS:MixSegment, 0 + JE SetStereo1 + + Call StopAD1816 + Call StartAD1816 + +SetStereo1: + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include loadsam.inc + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset ESSScreenList + + ClC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far + + Xor AH, AH + Mov AL, [CS:VolumeTable+DI] + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UpdateSoundcardVariables + + Mov AL, 4 + Mov BX, 3F3Fh + Sub BX, [Word Ptr CS:VolumeTable] + Call AD1816RegisterOut + + Mov AL, 33 + Mov BX, 40h + Call AD1816RegisterOut + + Mov AL, 39 + Call AD1816RegisterIn + Mov CL, [CS:VolumeTable+2] + ShL CX, 9 + And BX, 0110000111111111b + Or BX, CX + Call AD1816RegisterOut + + Mov AL, 14 + Xor BX, BX + Call AD1816RegisterOut + + Mov AL, 44 + Xor BX, BX + Call AD1816RegisterOut + + Ret + +EndP UpdateSoundcardVariables + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far + + Push DS + Push DX + + Push CS + Pop DS + Assume DS:Driver + + Mov [VolumeTable+DI], AL + Call UpdateSoundcardVariables + + Pop DX + Pop DS + Ret + +EndP SetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. + +StopAfterPlay DW 0 +DefaultChannels DW 64 + DW 5 Dup (0) + + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/AMD3DI.MIX b/SoundDrivers/AMD3DI.MIX new file mode 100755 index 0000000..dc3a759 --- /dev/null +++ b/SoundDrivers/AMD3DI.MIX @@ -0,0 +1,56 @@ + +; 8-bit interpolated mixing routine, 4 samples at a time. Rearranged +; MM7 contains volume as packed floating point +; MM6 contains offset as packed integer offset +; MM5 = DeltaOffset + +; MM7 = RVol|LVol +; MM6 = (1-Offset2)|Offset2|(1-Offset1)|Offset1 + + MovD MM0, [SampleBlock1] ; MM0 = x|x|x|x|S2H|S2L|S1H|S1L + MovQ MM2, MM6 + + PSRAW MM2, 1 + PUnpckLBW MM0, MM0 ; MM0 = S2H|S2L|S1H|S1L + + PAddW MM6, MM5 + PMAddWD MM0, MM2 ; MM0 = IS2|IS1 + + MovD MM1, [SampleBlock2] ; MM1 = x|x|x|x|S4H|S4L|S3H|S3L + MovQ MM2, MM6 + + PUnpckLBW MM1, MM1 ; MM1 = S4H|S4L|S3H|S3L + PSRAW MM2, 1 + + PI2FD MM0, MM0 ; MM0 = FIS2|FIS1 + PMAddWD MM1, MM2 ; MM1 = IS4|IS3 + + MovQ MM2, MM0 + PUnpckLDQ MM0, MM0 ; MM0 = FIS1|FIS1 + + PUnpckHDQ MM2, MM2 ; MM2 = FIS2|FIS2 + PI2FD MM1, MM1 ; MM1 = FIS4|FIS3 + + PFMul MM0, MM7 ; MM0 = R1|L1 + PAddW MM6, MM5 + + PFMul MM2, MM7 ; MM2 = R2|L2 + MovQ MM3, MM1 + + PFAdd MM0, [Buffer1] + PUnpckLDQ MM1, MM1 ; MM1 = FIS3|FIS3 + + PFAdd MM2, [Buffer2] + PUnpckHDQ MM3, MM3 ; MM3 = FIS4|FIS4 + + PFMul MM1, MM7 + MovQ [Buffer1], MM0 + + PFMul MM3, MM7 + PFAdd MM1, [Buffer3] + + MovQ [Buffer2], MM2 + PFAdd MM3, [Buffer4] + + MovQ [Buffer3], MM1 + MovQ [Buffer4], MM3 diff --git a/SoundDrivers/AMD3DNI.MIX b/SoundDrivers/AMD3DNI.MIX new file mode 100755 index 0000000..203d218 --- /dev/null +++ b/SoundDrivers/AMD3DNI.MIX @@ -0,0 +1,304 @@ + +; 8-bit non interpolated mixing routine, 8 samples at a time. Not rearranged + +; MM7 contains volume as packed floating point MM7 = RVol|LVol + + MovD MM0, [SampleBlock1] ; Low 4 bytes contain samples 1-4 + MovD MM1, [SampleBlock2] ; Low 4 bytes contain samples 5-8 + + PUnpckLBW MM0, MM0 ; MM0 = S4|S3|S2|S1 + PUnpckLBW MM1, MM1 ; MM1 = S8|S7|S6|S5 + + MovQ MM2, MM0 + MovQ MM3, MM1 + + PUnpckLWD MM0, MM0 ; MM0 = S2|S1 + PUnpckLWD MM1, MM1 ; MM1 = S6|S5 + + PUnpckHWD MM2, MM2 ; MM2 = S4|S3 + PUnpckHWD MM3, MM3 ; MM3 = S8|S7 + +; What category do PI2FD instructions fall under? Are they AMD-3D ALU (ie. +; only one resource shared between pipes?) + + PI2FD MM0, MM0 ; MM0 = FS2|FS1 + PI2FD MM1, MM1 ; MM1 = FS6|FS5 + PI2FD MM2, MM2 ; MM2 = FS4|FS3 + PI2FD MM3, MM3 ; MM3 = FS8|FS7 + + MovQ MM4, MM0 + MovQ MM5, MM2 + + PUnpckLDQ MM0, MM0 ; MM0 = FS1|FS1 + PUnpckHDQ MM4, MM4 ; MM4 = FS2|FS2 + PUnpckLDQ MM2, MM2 ; MM2 = FS3|FS3 + PUnpckHDQ MM5, MM5 ; MM5 = FS4|FS4 + + PFMul MM0, MM7 ; MM0 = R1|L1 + PFMul MM4, MM7 ; MM4 = R2|L2 + PFMul MM2, MM7 ; MM2 = R3|L3 + PFMul MM5, MM7 ; MM5 = R4|L4 + + PFAdd MM0, [Buffer1] + PFAdd MM4, [Buffer2] + PFAdd MM2, [Buffer3] + PFAdd MM5, [Buffer4] + + MovQ [Buffer1], MM0 + MovQ [Buffer2], MM4 + MovQ [Buffer3], MM2 + MovQ [Buffer4], MM5 + + MovQ MM0, MM1 + MovQ MM2, MM3 + + PUnpckLDQ MM0, MM0 ; MM0 = FS5|FS5 + PUnpckHDQ MM1, MM1 ; MM1 = FS6|FS6 + PUnpckLDQ MM2, MM2 ; MM2 = FS7|FS7 + PUnpckHDQ MM3, MM3 ; MM3 = FS8|FS8 + + PFMul MM0, MM7 + PFMul MM1, MM7 + PFMul MM2, MM7 + PFMul MM3, MM7 + + PFAdd MM0, [Buffer5] + PFAdd MM1, [Buffer6] + PFAdd MM2, [Buffer7] + PFAdd MM3, [Buffer8] + + MovQ [Buffer5], MM0 + MovQ [Buffer6], MM1 + MovQ [Buffer7], MM2 + MovQ [Buffer8], MM3 + +;----------------------------------------------------------------------------- +; Rearranged to improve pairing +; MM7 contains volume as packed floating point MM7 = RVol|LVol + + MovD MM0, [SampleBlock1] ; Low 4 bytes contain samples 1-4 + MovD MM1, [SampleBlock2] ; Low 4 bytes contain samples 5-8 + + PUnpckLBW MM0, MM0 ; MM0 = S4|S3|S2|S1 + PUnpckLBW MM1, MM1 ; MM1 = S8|S7|S6|S5 + + MovQ MM2, MM0 + PUnpckLWD MM0, MM0 ; MM0 = S2|S1 + + MovQ MM3, MM1 + PUnpckLWD MM1, MM1 ; MM1 = S6|S5 + + PUnpckHWD MM2, MM2 ; MM2 = S4|S3 + PI2FD MM0, MM0 ; MM0 = FS2|FS1 + + PUnpckHWD MM3, MM3 ; MM3 = S8|S7 + PI2FD MM1, MM1 ; MM1 = FS6|FS5 + + MovQ MM4, MM0 + PI2FD MM2, MM2 ; MM2 = FS4|FS3 + + MovQ MM5, MM2 + PI2FD MM3, MM3 ; MM3 = FS8|FS7 + + PUnpckLDQ MM0, MM0 ; MM0 = FS1|FS1 + PUnpckHDQ MM4, MM4 ; MM4 = FS2|FS2 + + PFMul MM0, MM7 ; MM0 = R1|L1 + PUnpckLDQ MM2, MM2 ; MM2 = FS3|FS3 + + PFMul MM4, MM7 ; MM4 = R2|L2 + PUnpckHDQ MM5, MM5 ; MM5 = FS4|FS4 + + PFMul MM2, MM7 ; MM2 = R3|L3 + PFAdd MM0, [Buffer1] + + PFMul MM5, MM7 ; MM5 = R4|L4 + PFAdd MM4, [Buffer2] + + PFAdd MM2, [Buffer3] + MovQ [Buffer1], MM0 + + MovQ [Buffer2], MM4 + PFAdd MM5, [Buffer4] + + MovQ [Buffer3], MM2 + MovQ MM0, MM1 + + MovQ [Buffer4], MM5 + MovQ MM2, MM3 + + PUnpckLDQ MM0, MM0 ; MM0 = FS5|FS5 + PUnpckHDQ MM1, MM1 ; MM1 = FS6|FS6 + + PFMul MM0, MM7 + PUnpckLDQ MM2, MM2 ; MM2 = FS7|FS7 + + PFMul MM1, MM7 + PUnpckHDQ MM3, MM3 ; MM3 = FS8|FS8 + + PFAdd MM0, [Buffer5] + PFMul MM2, MM7 + + PFAdd MM1, [Buffer6] + PFMul MM3, MM7 + + MovQ [Buffer5], MM0 + PFAdd MM2, [Buffer7] + + MovQ [Buffer6], MM1 + PFAdd MM3, [Buffer8] + + MovQ [Buffer7], MM2 ; These will be rearranged to match + MovQ [Buffer8], MM3 ; the next iteration. + + + +; 16-bit non interpolated mixing routine, 8 samples at a time. Not rearranged + +; MM7 contains volume as packed floating point MM7 = RVol|LVol + + MovQ MM0, [SampleBlock1] ; MM0 = S4|S3|S2|S1 + MovQ MM1, [SampleBlock2] ; MM1 = S8|S7|S6|S5 + + MovQ MM2, MM0 + MovQ MM3, MM1 + + PUnpckLWD MM0, MM0 ; MM0 = S2|S1 + PUnpckLWD MM1, MM1 ; MM1 = S6|S5 + + PUnpckHWD MM2, MM2 ; MM2 = S4|S3 + PUnpckHWD MM3, MM3 ; MM3 = S8|S7 + +; What category do PI2FD instructions fall under? Are they AMD-3D ALU (ie. +; only one resource shared between pipes?) + + PI2FD MM0, MM0 ; MM0 = FS2|FS1 + PI2FD MM1, MM1 ; MM1 = FS6|FS5 + PI2FD MM2, MM2 ; MM2 = FS4|FS3 + PI2FD MM3, MM3 ; MM3 = FS8|FS7 + + MovQ MM4, MM0 + MovQ MM5, MM2 + + PUnpckLDQ MM0, MM0 ; MM0 = FS1|FS1 + PUnpckHDQ MM4, MM4 ; MM4 = FS2|FS2 + PUnpckLDQ MM2, MM2 ; MM2 = FS3|FS3 + PUnpckHDQ MM5, MM5 ; MM5 = FS4|FS4 + + PFMul MM0, MM7 ; MM0 = R1|L1 + PFMul MM4, MM7 ; MM4 = R2|L2 + PFMul MM2, MM7 ; MM2 = R3|L3 + PFMul MM5, MM7 ; MM5 = R4|L4 + + PFAdd MM0, [Buffer1] + PFAdd MM4, [Buffer2] + PFAdd MM2, [Buffer3] + PFAdd MM5, [Buffer4] + + MovQ [Buffer1], MM0 + MovQ [Buffer2], MM4 + MovQ [Buffer3], MM2 + MovQ [Buffer4], MM5 + + MovQ MM0, MM1 + MovQ MM2, MM3 + + PUnpckLDQ MM0, MM0 ; MM0 = FS5|FS5 + PUnpckHDQ MM1, MM1 ; MM1 = FS6|FS6 + PUnpckLDQ MM2, MM2 ; MM2 = FS7|FS7 + PUnpckHDQ MM3, MM3 ; MM3 = FS8|FS8 + + PFMul MM0, MM7 + PFMul MM1, MM7 + PFMul MM2, MM7 + PFMul MM3, MM7 + + PFAdd MM0, [Buffer5] + PFAdd MM1, [Buffer6] + PFAdd MM2, [Buffer7] + PFAdd MM3, [Buffer8] + + MovQ [Buffer5], MM0 + MovQ [Buffer6], MM1 + MovQ [Buffer7], MM2 + MovQ [Buffer8], MM3 + +;----------------------------------------------------------------------------- +; Rearranged to improve pairing +; MM7 contains volume as packed floating point MM7 = RVol|LVol + + MovQ MM0, [SampleBlock1] ; MM0 = S4|S3|S2|S1 + MovQ MM1, [SampleBlock2] ; MM1 = S8|S7|S6|S5 + + MovQ MM2, MM0 + PUnpckLWD MM0, MM0 ; MM0 = S2|S1 + + MovQ MM3, MM1 + PUnpckLWD MM1, MM1 ; MM1 = S6|S5 + + PI2FD MM0, MM0 ; MM0 = FS2|FS1 + PUnpckHWD MM2, MM2 ; MM2 = S4|S3 + + PI2FD MM1, MM1 ; MM1 = FS6|FS5 + PUnpckHWD MM3, MM3 ; MM3 = S8|S7 + +; What category do PI2FD instructions fall under? Are they AMD-3D ALU (ie. +; only one resource shared between pipes?) + + MovQ MM4, MM0 + PI2FD MM2, MM2 ; MM2 = FS4|FS3 + + MovQ MM5, MM2 + PI2FD MM3, MM3 ; MM3 = FS8|FS7 + + PUnpckLDQ MM0, MM0 ; MM0 = FS1|FS1 + PUnpckHDQ MM4, MM4 ; MM4 = FS2|FS2 + + PFMul MM0, MM7 ; MM0 = R1|L1 + PUnpckLDQ MM2, MM2 ; MM2 = FS3|FS3 + + PFMul MM4, MM7 ; MM4 = R2|L2 + PUnpckHDQ MM5, MM5 ; MM5 = FS4|FS4 + + PFAdd MM0, [Buffer1] + PFMul MM2, MM7 ; MM2 = R3|L3 + + PFAdd MM4, [Buffer2] + PFMul MM5, MM7 ; MM5 = R4|L4 + + PFAdd MM2, [Buffer3] + MovQ [Buffer1], MM0 + + PFAdd MM5, [Buffer4] + MovQ [Buffer2], MM4 + + MovQ MM0, MM1 + MovQ [Buffer3], MM2 + + MovQ MM2, MM3 + MovQ [Buffer4], MM5 + + PUnpckLDQ MM0, MM0 ; MM0 = FS5|FS5 + PUnpckHDQ MM1, MM1 ; MM1 = FS6|FS6 + + PFMul MM0, MM7 + PUnpckLDQ MM2, MM2 ; MM2 = FS7|FS7 + + PFMul MM1, MM7 + PUnpckHDQ MM3, MM3 ; MM3 = FS8|FS8 + + PFAdd MM0, [Buffer5] + PFMul MM2, MM7 + + PFAdd MM1, [Buffer6] + PFMul MM3, MM7 + + MovQ [Buffer5], MM0 + PFAdd MM2, [Buffer7] + + MovQ [Buffer6], MM1 + PFAdd MM3, [Buffer8] + + MovQ [Buffer7], MM2 + MovQ [Buffer8], MM3 + diff --git a/SoundDrivers/AWE32B.ASM b/SoundDrivers/AWE32B.ASM new file mode 100755 index 0000000..d728681 --- /dev/null +++ b/SoundDrivers/AWE32B.ASM @@ -0,0 +1,4310 @@ + + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + + Comment ~ + +Index = BasePort + 802h + + 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ + ³ .............................. ³ Register ³ Channel Number ³ + ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + + + ~ + +OldIRQHandler DD 0 +AWEMemory DD 0 +AWEMemoryUsed DD 0 +AWEUpdateCount DW 0 + +AWEUpdateTimer DW 0 + +LoadSampleFuncF DW 0 +LoadSampleFuncB DW 0 + +AWEDataTable DD 5*100 Dup (0) ; Start, Startloop, Endloop, Size +MIDIPort DW 0 +MIDIBuffer DB 256 Dup (0) +MIDIBufferHead DB 0 +MIDIBufferTail DB 0 + +SB16BasePort DW 0 +MixerPort DW 0 +Step DW 1 +AWEUpdateFlag DB 0 +Compress DB 0 + DB 0 + +SBIRQMode DB 0 +BlockLength DW 100 +BlockLength2 DW 100 + +AWE32Msg DB "Sound Blaster AWE 32 detected", 13 + DB "Address ", 0FDh, "Xh, ", 0FDh, "Dk Memory", 0 + +AWE32Msg2 DB "Sound Blaster AWE 32 detected", 13 + DB "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, ", 0FDh, "Dk RAM", 0 + +AWE32Status DB "FreeAWE ", 0FDh, "Dk", 0 + +AWE32ReinitMsg DB "Sound Blaster AWE 32 reinitialised", 0 +Stereo DB 0 +Forced DB 0 +DriverName DB "ITAWE32B.DRV", 0 + +FrequencyError DB "AWE Hardware frequency limit exceeded -> Note terminated", 0 + +IRQFlag DB 0FFh + +IRQData Label Word + DW 20h, 1111111111111110b ; IRQ 0 + DW 24h, 1111111111111101b ; IRQ 1 + DW 28h, 1111110111111011b ; IRQ 2 + DW 2Ch, 1111111111110111b ; IRQ 3 + DW 30h, 1111111111101111b ; IRQ 4 + DW 34h, 1111111111011111b ; IRQ 5 + DW 38h, 1111111110111111b ; IRQ 6 + DW 3Ch, 1111111101111111b ; IRQ 7 + DW 1C0h, 1111111011111011b ; IRQ 8 + DW 1C4h, 1111110111111011b ; IRQ 9 + DW 1C8h, 1111101111111011b ; IRQ 10 + DW 1CCh, 1111011111111011b ; IRQ 11 + DW 1D0h, 1110111111111011b ; IRQ 12 + DW 1D4h, 1101111111111011b ; IRQ 13 + DW 1D8h, 1011111111111011b ; IRQ 14 + DW 1DCh, 0111111111111011b ; IRQ 15 + +IMR DW 0 + + CPF EQU 0 + PTRX EQU 20h + CVCF EQU 40h + VTFT EQU 60h + PSST EQU 0C0h + CSL EQU 0E0h + + CCCA EQU 100h + HWCF4 EQU 129h + HWCF5 EQU 12Ah + HWCF6 EQU 12Dh + SMALR EQU 134h + SMARR EQU 135h + SMALW EQU 136h + SMARW EQU 137h + SMLD EQU 43Ah + SMRD EQU 23Ah + WC EQU 23Bh + HWCF1 EQU 43Dh + HWCF2 EQU 43Eh + CFG2 EQU 43Eh + HWCF3 EQU 43Fh + INIT1 EQU 440h + INIT2 EQU 240h + INIT3 EQU 460h + INIT4 EQU 260h + ENVVOL EQU 480h + DCYSUSV EQU 4A0h + ENVVAL EQU 4C0h + DCYSUS EQU 4E0h + SUSDCY EQU 4E0h + ATKHLDV EQU 280h + LFO1VAL EQU 2A0h + ATKHLD EQU 2C0h + HLDATK EQU 2C0h + LFO2VAL EQU 2E0h + IP EQU 300h + IFATN EQU 320h + PEFE EQU 340h + FMMOD EQU 360h + TREMFRQ EQU 380h + FM2FRQ2 EQU 3A0h + +ALIGN 4 + +InitTable1 Label + DW 003FFh, 0030h, 007FFh, 0130h, 00BFFh, 0230h, 00FFFh, 0330h + DW 013FFh, 0430h, 017FFh, 0530h, 01BFFh, 0630h, 01FFFh, 0730h + DW 023FFh, 0830h, 027FFh, 0930h, 02BFFh, 0A30h, 02FFFh, 0B30h + DW 033FFh, 0C30h, 037FFh, 0D30h, 03BFFh, 0E30h, 03FFFh, 0F30h + + DW 043FFh, 0030h, 047FFh, 0130h, 04BFFh, 0230h, 04FFFh, 0330h + DW 053FFh, 0430h, 057FFh, 0530h, 05BFFh, 0630h, 05FFFh, 0730h + DW 063FFh, 0830h, 067FFh, 0930h, 06BFFh, 0A30h, 06FFFh, 0B30h + DW 073FFh, 0C30h, 077FFh, 0D30h, 07BFFh, 0E30h, 07FFFh, 0F30h + + DW 083FFh, 0030h, 087FFh, 0130h, 08BFFh, 0230h, 08FFFh, 0330h + DW 093FFh, 0430h, 097FFh, 0530h, 09BFFh, 0630h, 09FFFh, 0730h + DW 0A3FFh, 0830h, 0A7FFh, 0930h, 0ABFFh, 0A30h, 0AFFFh, 0B30h + DW 0B3FFh, 0C30h, 0B7FFh, 0D30h, 0BBFFh, 0E30h, 0BFFFh, 0F30h + + DW 0C3FFh, 0030h, 0C7FFh, 0130h, 0CBFFh, 0230h, 0CFFFh, 0330h + DW 0D3FFh, 0430h, 0D7FFh, 0530h, 0DBFFh, 0630h, 0DFFFh, 0730h + DW 0E3FFh, 0830h, 0E7FFh, 0930h, 0EBFFh, 0A30h, 0EFFFh, 0B30h + DW 0F3FFh, 0C30h, 0F7FFh, 0D30h, 0FBFFh, 0E30h, 0FFFFh, 0F30h + +InitTable2 Label + DW 003FFh, 8030h, 007FFh, 8130h, 00BFFh, 8230h, 00FFFh, 8330h + DW 013FFh, 8430h, 017FFh, 8530h, 01BFFh, 8630h, 01FFFh, 8730h + DW 023FFh, 8830h, 027FFh, 8930h, 02BFFh, 8A30h, 02FFFh, 8B30h + DW 033FFh, 8C30h, 037FFh, 8D30h, 03BFFh, 8E30h, 03FFFh, 8F30h + + DW 043FFh, 8030h, 047FFh, 8130h, 04BFFh, 8230h, 04FFFh, 8330h + DW 053FFh, 8430h, 057FFh, 8530h, 05BFFh, 8630h, 05FFFh, 8730h + DW 063FFh, 8830h, 067FFh, 8930h, 06BFFh, 8A30h, 06FFFh, 8B30h + DW 073FFh, 8C30h, 077FFh, 8D30h, 07BFFh, 8E30h, 07FFFh, 8F30h + + DW 083FFh, 8030h, 087FFh, 8130h, 08BFFh, 8230h, 08FFFh, 8330h + DW 093FFh, 8430h, 097FFh, 8530h, 09BFFh, 8630h, 09FFFh, 8730h + DW 0A3FFh, 8830h, 0A7FFh, 8930h, 0ABFFh, 8A30h, 0AFFFh, 8B30h + DW 0B3FFh, 8C30h, 0B7FFh, 8D30h, 0BBFFh, 8E30h, 0BFFFh, 8F30h + + DW 0C3FFh, 8030h, 0C7FFh, 8130h, 0CBFFh, 8230h, 0CFFFh, 8330h + DW 0D3FFh, 8430h, 0D7FFh, 8530h, 0DBFFh, 8630h, 0DFFFh, 8730h + DW 0E3FFh, 8830h, 0E7FFh, 8930h, 0EBFFh, 8A30h, 0EFFFh, 8B30h + DW 0F3FFh, 8C30h, 0F7FFh, 8D30h, 0FBFFh, 8E30h, 0FFFFh, 8F30h + +InitTable3 Label + DW 0C10h, 8470h, 14FEh, 0B488h, 167Fh, 0A470h, 18E7h, 84B5h + DW 1B6Eh, 842Ah, 1F1Dh, 852Ah, 0DA3h, 8F7Ch, 167Eh, 7254h + DW 0, 842Ah, 1, 852Ah, 18E6h, 8BAAh, 1B6Dh, 7234h + DW 229Fh, 8429h, 2746h, 8529h, 1F1Ch, 86E7h, 229Eh, 7224h + + DW 0DA4h, 8429h, 2C29h, 8529h, 2745h, 87F6h, 2C28h, 7254h + DW 383Bh, 8428h, 320Fh, 8528h, 320Eh, 8F02h, 1341h, 7264h + DW 3EB6h, 8428h, 3EB9h, 8528h, 383Ah, 8FA9h, 3EB5h, 7294h + DW 3EB7h, 8474h, 3EBAh, 8575h, 3EB8h, 0C4C3h, 3EBBh, 45C3h + + DW 00000, 0A404h, 00001, 0A504h, 141Fh, 8671h, 14FDh, 8287h + DW 3EBCh, 0E610h, 3EC8h, 8C7Bh, 31Ah, 87E6h, 3EC8h, 86F7h + DW 3EC0h, 821Eh, 3EBEh, 0D208h, 3EBDh, 821Fh, 3ECAh, 8386h + DW 3EC1h, 8C03h, 3EC9h, 831Eh, 3ECAh, 8C4Ch, 3EBFh, 8C55h + + DW 3EC9h, 0C208h, 3EC4h, 0BC84h, 3EC8h, 8EADh, 3EC8h, 0D308h + DW 3EC2h, 8F7Eh, 3ECBh, 821Eh, 3ECBh, 0D208h, 3EC5h, 831Fh + DW 3EC6h, 0C308h, 3EC3h, 32FFh, 3EC9h, 8265h, 3EC9h, 831Eh + DW 1342h, 0D308h, 3EC7h, 33FFh, 0, 8365h, 1420h, 9570h + +InitTable4 Label + DW 0C10h, 8470h, 14FEh, 0B488h, 167Fh, 0A470h, 18E7h, 84B5h + DW 1B6Eh, 842Ah, 1F1Dh, 852Ah, 0DA3h, 0F7Ch, 167Eh, 7254h + DW 0, 842Ah, 1, 852Ah, 18E6h, 0BAAh, 1B6Dh, 7234h + DW 229Fh, 8429h, 2746h, 8529h, 1F1Ch, 6E7h, 229Eh, 7224h + + DW 0DA4h, 8429h, 2C29h, 8529h, 2745h, 07F6h, 2C28h, 7254h + DW 383Bh, 8428h, 320Fh, 8528h, 320Eh, 0F02h, 1341h, 7264h + DW 3EB6h, 8428h, 3EB9h, 8528h, 383Ah, 0FA9h, 3EB5h, 7294h + DW 3EB7h, 8474h, 3EBAh, 8575h, 3EB8h, 44C3h, 3EBBh, 45C3h + + DW 00000, 0A404h, 00001, 0A504h, 141Fh, 0671h, 14FDh, 287h + DW 3EBCh, 0E610h, 3EC8h, 0C7Bh, 31Ah, 7E6h, 3EC8h, 86F7h + DW 3EC0h, 821Eh, 3EBEh, 0D208h, 3EBDh, 021Fh, 3ECAh, 386h + DW 3EC1h, 0C03h, 3EC9h, 31Eh, 3ECAh, 8C4Ch, 3EBFh, 0C55h + + DW 3EC9h, 0C208h, 3EC4h, 0BC84h, 3EC8h, 0EADh, 3EC8h, 0D308h + DW 3EC2h, 8F7Eh, 3ECBh, 021Eh, 3ECBh, 0D208h, 3EC5h, 31Fh + DW 3EC6h, 0C308h, 3EC3h, 32FFh, 3EC9h, 0265h, 3EC9h, 831Eh + DW 1342h, 0D308h, 3EC7h, 33FFh, 0, 8365h, 1420h, 9570h + +AWEVolumeTable Label Byte ; Value = -log(vol/256)*(20/.375) + ; = -log(vol/256)*(160/3) + + DB 255, 128, 112, 103, 96, 91, 87, 83 ; 0->7 + DB 80, 78, 75, 73, 71, 69, 67, 66 ; 8->15 + DB 64, 63, 61, 60, 59, 58, 57, 56 ; 16->23 + DB 55, 54, 53, 52, 51, 50, 50, 49 ; 24->31 + DB 48, 47, 47, 46, 45, 45, 44, 44 ; 32->39 + DB 43, 42, 42, 41, 41, 40, 40, 39 ; 40->47 + DB 39, 38, 38, 37, 37, 36, 36, 36 ; 48->55 + DB 35, 35, 34, 34, 34, 33, 33, 32 ; 56->63 + DB 32, 32, 31, 31, 31, 30, 30, 30 ; 64->71 + DB 29, 29, 29, 28, 28, 28, 28, 27 ; 72->79 + DB 27, 27, 26, 26, 26, 26, 25, 25 ; 80->87 + DB 25, 25, 24, 24, 24, 23, 23, 23 ; 88->95 + DB 23, 22, 22, 22, 22, 22, 21, 21 ; 96->103 + DB 21, 21, 20, 20, 20, 20, 20, 19 ; 104->111 + DB 19, 19, 19, 19, 18, 18, 18, 18 ; 112->119 + DB 18, 17, 17, 17, 17, 17, 16, 16 ; 120->127 + DB 16 ; 128 + + Comment ~ ; Value = -log(vol/128)*(20/.375) + ; = -log(vol/128)*(160/3) + ; This is mathematically the correct table, but it seems too + ; loud, and it overloads on playback. + + DB 255, 112, 96, 87, 80, 75, 71, 67 ; 0->7 + DB 64, 61, 59, 57, 55, 53, 51, 50 ; 8->15 + DB 48, 47, 45, 44, 43, 42, 41, 40 ; 16->23 + DB 39, 38, 37, 36, 35, 34, 34, 33 ; 24->31 + DB 32, 31, 31, 30, 29, 29, 28, 28 ; 32->39 + DB 27, 26, 26, 25, 25, 24, 24, 23 ; 40->47 + DB 23, 22, 22, 21, 21, 20, 20, 20 ; 48->55 + DB 19, 19, 18, 18, 18, 17, 17, 16 ; 56->63 + DB 16, 16, 15, 15, 15, 14, 14, 14 ; 64->71 + DB 13, 13, 13, 13, 12, 12, 12, 11 ; 72->79 + DB 11, 11, 10, 10, 10, 9, 9, 9 ; 80->87 + DB 9, 8, 8, 8, 8, 7, 7, 7 ; 88->95 + DB 7, 6, 6, 6, 6, 5, 5, 5 ; 96->103 + DB 5, 4, 4, 4, 4, 4, 4, 3 ; 104->111 + DB 3, 3, 3, 2, 2, 2, 2, 2 ; 112->119 + DB 1, 1, 1, 1, 1, 1, 1, 1 ; 120->127 + DB 0 + + ~ + +AWEPitchTable Label DWord ; Pitchval = 88200 * 2^(Pos / 4096) + DD 88200, 88215, 88230, 88245, 88260, 88275, 88290, 88305 + DD 88320, 88335, 88350, 88365, 88380, 88395, 88410, 88425 + DD 88440, 88455, 88470, 88485, 88500, 88514, 88529, 88544 + DD 88559, 88574, 88589, 88604, 88619, 88634, 88649, 88664 + DD 88679, 88694, 88709, 88724, 88739, 88754, 88770, 88785 + DD 88800, 88815, 88830, 88845, 88860, 88875, 88890, 88905 + DD 88920, 88935, 88950, 88965, 88980, 88995, 89010, 89025 + DD 89040, 89055, 89070, 89086, 89101, 89116, 89131, 89146 + DD 89161, 89176, 89191, 89206, 89221, 89236, 89252, 89267 + DD 89282, 89297, 89312, 89327, 89342, 89357, 89372, 89388 + DD 89403, 89418, 89433, 89448, 89463, 89478, 89493, 89509 + DD 89524, 89539, 89554, 89569, 89584, 89600, 89615, 89630 + DD 89645, 89660, 89675, 89691, 89706, 89721, 89736, 89751 + DD 89767, 89782, 89797, 89812, 89827, 89842, 89858, 89873 + DD 89888, 89903, 89919, 89934, 89949, 89964, 89979, 89995 + DD 90010, 90025, 90040, 90056, 90071, 90086, 90101, 90117 + DD 90132, 90147, 90162, 90178, 90193, 90208, 90223, 90239 + DD 90254, 90269, 90284, 90300, 90315, 90330, 90346, 90361 + DD 90376, 90391, 90407, 90422, 90437, 90453, 90468, 90483 + DD 90499, 90514, 90529, 90545, 90560, 90575, 90591, 90606 + DD 90621, 90637, 90652, 90667, 90683, 90698, 90713, 90729 + DD 90744, 90759, 90775, 90790, 90805, 90821, 90836, 90852 + DD 90867, 90882, 90898, 90913, 90928, 90944, 90959, 90975 + DD 90990, 91005, 91021, 91036, 91052, 91067, 91082, 91098 + DD 91113, 91129, 91144, 91160, 91175, 91190, 91206, 91221 + DD 91237, 91252, 91268, 91283, 91299, 91314, 91329, 91345 + DD 91360, 91376, 91391, 91407, 91422, 91438, 91453, 91469 + DD 91484, 91500, 91515, 91531, 91546, 91562, 91577, 91593 + DD 91608, 91624, 91639, 91655, 91670, 91686, 91701, 91717 + DD 91732, 91748, 91763, 91779, 91794, 91810, 91825, 91841 + DD 91856, 91872, 91887, 91903, 91919, 91934, 91950, 91965 + DD 91981, 91996, 92012, 92028, 92043, 92059, 92074, 92090 + DD 92105, 92121, 92137, 92152, 92168, 92183, 92199, 92215 + DD 92230, 92246, 92261, 92277, 92293, 92308, 92324, 92340 + DD 92355, 92371, 92386, 92402, 92418, 92433, 92449, 92465 + DD 92480, 92496, 92512, 92527, 92543, 92559, 92574, 92590 + DD 92606, 92621, 92637, 92653, 92668, 92684, 92700, 92715 + DD 92731, 92747, 92762, 92778, 92794, 92810, 92825, 92841 + DD 92857, 92872, 92888, 92904, 92920, 92935, 92951, 92967 + DD 92982, 92998, 93014, 93030, 93045, 93061, 93077, 93093 + DD 93108, 93124, 93140, 93156, 93171, 93187, 93203, 93219 + DD 93235, 93250, 93266, 93282, 93298, 93313, 93329, 93345 + DD 93361, 93377, 93392, 93408, 93424, 93440, 93456, 93472 + DD 93487, 93503, 93519, 93535, 93551, 93566, 93582, 93598 + DD 93614, 93630, 93646, 93662, 93677, 93693, 93709, 93725 + DD 93741, 93757, 93773, 93788, 93804, 93820, 93836, 93852 + DD 93868, 93884, 93900, 93915, 93931, 93947, 93963, 93979 + DD 93995, 94011, 94027, 94043, 94059, 94075, 94090, 94106 + DD 94122, 94138, 94154, 94170, 94186, 94202, 94218, 94234 + DD 94250, 94266, 94282, 94298, 94314, 94330, 94346, 94362 + DD 94377, 94393, 94409, 94425, 94441, 94457, 94473, 94489 + DD 94505, 94521, 94537, 94553, 94569, 94585, 94601, 94617 + DD 94633, 94649, 94665, 94681, 94697, 94713, 94729, 94746 + DD 94762, 94778, 94794, 94810, 94826, 94842, 94858, 94874 + DD 94890, 94906, 94922, 94938, 94954, 94970, 94986, 95002 + DD 95018, 95035, 95051, 95067, 95083, 95099, 95115, 95131 + DD 95147, 95163, 95179, 95196, 95212, 95228, 95244, 95260 + DD 95276, 95292, 95308, 95324, 95341, 95357, 95373, 95389 + DD 95405, 95421, 95437, 95454, 95470, 95486, 95502, 95518 + DD 95534, 95551, 95567, 95583, 95599, 95615, 95631, 95648 + DD 95664, 95680, 95696, 95712, 95729, 95745, 95761, 95777 + DD 95793, 95810, 95826, 95842, 95858, 95875, 95891, 95907 + DD 95923, 95939, 95956, 95972, 95988, 96004, 96021, 96037 + DD 96053, 96069, 96086, 96102, 96118, 96134, 96151, 96167 + DD 96183, 96200, 96216, 96232, 96248, 96265, 96281, 96297 + DD 96314, 96330, 96346, 96362, 96379, 96395, 96411, 96428 + DD 96444, 96460, 96477, 96493, 96509, 96526, 96542, 96558 + DD 96575, 96591, 96607, 96624, 96640, 96656, 96673, 96689 + DD 96706, 96722, 96738, 96755, 96771, 96787, 96804, 96820 + DD 96837, 96853, 96869, 96886, 96902, 96919, 96935, 96951 + DD 96968, 96984, 97001, 97017, 97033, 97050, 97066, 97083 + DD 97099, 97116, 97132, 97148, 97165, 97181, 97198, 97214 + DD 97231, 97247, 97264, 97280, 97296, 97313, 97329, 97346 + DD 97362, 97379, 97395, 97412, 97428, 97445, 97461, 97478 + DD 97494, 97511, 97527, 97544, 97560, 97577, 97593, 97610 + DD 97626, 97643, 97659, 97676, 97692, 97709, 97726, 97742 + DD 97759, 97775, 97792, 97808, 97825, 97841, 97858, 97874 + DD 97891, 97908, 97924, 97941, 97957, 97974, 97990, 98007 + DD 98024, 98040, 98057, 98073, 98090, 98107, 98123, 98140 + DD 98156, 98173, 98190, 98206, 98223, 98240, 98256, 98273 + DD 98289, 98306, 98323, 98339, 98356, 98373, 98389, 98406 + DD 98423, 98439, 98456, 98473, 98489, 98506, 98523, 98539 + DD 98556, 98573, 98589, 98606, 98623, 98639, 98656, 98673 + DD 98689, 98706, 98723, 98740, 98756, 98773, 98790, 98806 + DD 98823, 98840, 98857, 98873, 98890, 98907, 98924, 98940 + DD 98957, 98974, 98990, 99007, 99024, 99041, 99058, 99074 + DD 99091, 99108, 99125, 99141, 99158, 99175, 99192, 99208 + DD 99225, 99242, 99259, 99276, 99292, 99309, 99326, 99343 + DD 99360, 99377, 99393, 99410, 99427, 99444, 99461, 99477 + DD 99494, 99511, 99528, 99545, 99562, 99579, 99595, 99612 + DD 99629, 99646, 99663, 99680, 99697, 99713, 99730, 99747 + DD 99764, 99781, 99798, 99815, 99832, 99849, 99865, 99882 + DD 99899, 99916, 99933, 99950, 99967, 99984, 100001, 100018 + DD 100035, 100051, 100068, 100085, 100102, 100119, 100136, 100153 + DD 100170, 100187, 100204, 100221, 100238, 100255, 100272, 100289 + DD 100306, 100323, 100340, 100357, 100374, 100391, 100408, 100425 + DD 100442, 100459, 100476, 100493, 100510, 100527, 100544, 100561 + DD 100578, 100595, 100612, 100629, 100646, 100663, 100680, 100697 + DD 100714, 100731, 100748, 100765, 100782, 100799, 100816, 100833 + DD 100850, 100867, 100885, 100902, 100919, 100936, 100953, 100970 + DD 100987, 101004, 101021, 101038, 101055, 101073, 101090, 101107 + DD 101124, 101141, 101158, 101175, 101192, 101209, 101227, 101244 + DD 101261, 101278, 101295, 101312, 101329, 101347, 101364, 101381 + DD 101398, 101415, 101432, 101450, 101467, 101484, 101501, 101518 + DD 101535, 101553, 101570, 101587, 101604, 101621, 101639, 101656 + DD 101673, 101690, 101707, 101725, 101742, 101759, 101776, 101793 + DD 101811, 101828, 101845, 101862, 101880, 101897, 101914, 101931 + DD 101949, 101966, 101983, 102000, 102018, 102035, 102052, 102069 + DD 102087, 102104, 102121, 102139, 102156, 102173, 102190, 102208 + DD 102225, 102242, 102260, 102277, 102294, 102312, 102329, 102346 + DD 102363, 102381, 102398, 102415, 102433, 102450, 102467, 102485 + DD 102502, 102520, 102537, 102554, 102572, 102589, 102606, 102624 + DD 102641, 102658, 102676, 102693, 102711, 102728, 102745, 102763 + DD 102780, 102797, 102815, 102832, 102850, 102867, 102884, 102902 + DD 102919, 102937, 102954, 102972, 102989, 103006, 103024, 103041 + DD 103059, 103076, 103094, 103111, 103129, 103146, 103163, 103181 + DD 103198, 103216, 103233, 103251, 103268, 103286, 103303, 103321 + DD 103338, 103356, 103373, 103391, 103408, 103426, 103443, 103461 + DD 103478, 103496, 103513, 103531, 103548, 103566, 103583, 103601 + DD 103618, 103636, 103653, 103671, 103689, 103706, 103724, 103741 + DD 103759, 103776, 103794, 103811, 103829, 103847, 103864, 103882 + DD 103899, 103917, 103934, 103952, 103970, 103987, 104005, 104022 + DD 104040, 104058, 104075, 104093, 104110, 104128, 104146, 104163 + DD 104181, 104199, 104216, 104234, 104252, 104269, 104287, 104304 + DD 104322, 104340, 104357, 104375, 104393, 104410, 104428, 104446 + DD 104463, 104481, 104499, 104516, 104534, 104552, 104570, 104587 + DD 104605, 104623, 104640, 104658, 104676, 104694, 104711, 104729 + DD 104747, 104764, 104782, 104800, 104818, 104835, 104853, 104871 + DD 104889, 104906, 104924, 104942, 104960, 104977, 104995, 105013 + DD 105031, 105048, 105066, 105084, 105102, 105120, 105137, 105155 + DD 105173, 105191, 105209, 105226, 105244, 105262, 105280, 105298 + DD 105315, 105333, 105351, 105369, 105387, 105405, 105422, 105440 + DD 105458, 105476, 105494, 105512, 105530, 105547, 105565, 105583 + DD 105601, 105619, 105637, 105655, 105672, 105690, 105708, 105726 + DD 105744, 105762, 105780, 105798, 105816, 105834, 105851, 105869 + DD 105887, 105905, 105923, 105941, 105959, 105977, 105995, 106013 + DD 106031, 106049, 106067, 106085, 106103, 106120, 106138, 106156 + DD 106174, 106192, 106210, 106228, 106246, 106264, 106282, 106300 + DD 106318, 106336, 106354, 106372, 106390, 106408, 106426, 106444 + DD 106462, 106480, 106498, 106516, 106534, 106552, 106570, 106588 + DD 106606, 106624, 106643, 106661, 106679, 106697, 106715, 106733 + DD 106751, 106769, 106787, 106805, 106823, 106841, 106859, 106877 + DD 106895, 106914, 106932, 106950, 106968, 106986, 107004, 107022 + DD 107040, 107058, 107077, 107095, 107113, 107131, 107149, 107167 + DD 107185, 107203, 107222, 107240, 107258, 107276, 107294, 107312 + DD 107331, 107349, 107367, 107385, 107403, 107421, 107440, 107458 + DD 107476, 107494, 107512, 107531, 107549, 107567, 107585, 107603 + DD 107622, 107640, 107658, 107676, 107694, 107713, 107731, 107749 + DD 107767, 107786, 107804, 107822, 107840, 107859, 107877, 107895 + DD 107913, 107932, 107950, 107968, 107986, 108005, 108023, 108041 + DD 108060, 108078, 108096, 108114, 108133, 108151, 108169, 108188 + DD 108206, 108224, 108243, 108261, 108279, 108297, 108316, 108334 + DD 108352, 108371, 108389, 108408, 108426, 108444, 108463, 108481 + DD 108499, 108518, 108536, 108554, 108573, 108591, 108609, 108628 + DD 108646, 108665, 108683, 108701, 108720, 108738, 108757, 108775 + DD 108793, 108812, 108830, 108849, 108867, 108886, 108904, 108922 + DD 108941, 108959, 108978, 108996, 109015, 109033, 109051, 109070 + DD 109088, 109107, 109125, 109144, 109162, 109181, 109199, 109218 + DD 109236, 109255, 109273, 109292, 109310, 109329, 109347, 109366 + DD 109384, 109403, 109421, 109440, 109458, 109477, 109495, 109514 + DD 109532, 109551, 109569, 109588, 109607, 109625, 109644, 109662 + DD 109681, 109699, 109718, 109736, 109755, 109774, 109792, 109811 + DD 109829, 109848, 109867, 109885, 109904, 109922, 109941, 109960 + DD 109978, 109997, 110015, 110034, 110053, 110071, 110090, 110108 + DD 110127, 110146, 110164, 110183, 110202, 110220, 110239, 110258 + DD 110276, 110295, 110314, 110332, 110351, 110370, 110388, 110407 + DD 110426, 110444, 110463, 110482, 110500, 110519, 110538, 110557 + DD 110575, 110594, 110613, 110631, 110650, 110669, 110688, 110706 + DD 110725, 110744, 110763, 110781, 110800, 110819, 110838, 110856 + DD 110875, 110894, 110913, 110931, 110950, 110969, 110988, 111007 + DD 111025, 111044, 111063, 111082, 111100, 111119, 111138, 111157 + DD 111176, 111195, 111213, 111232, 111251, 111270, 111289, 111307 + DD 111326, 111345, 111364, 111383, 111402, 111421, 111439, 111458 + DD 111477, 111496, 111515, 111534, 111553, 111571, 111590, 111609 + DD 111628, 111647, 111666, 111685, 111704, 111723, 111742, 111760 + DD 111779, 111798, 111817, 111836, 111855, 111874, 111893, 111912 + DD 111931, 111950, 111969, 111988, 112007, 112026, 112045, 112063 + DD 112082, 112101, 112120, 112139, 112158, 112177, 112196, 112215 + DD 112234, 112253, 112272, 112291, 112310, 112329, 112348, 112367 + DD 112386, 112405, 112424, 112443, 112462, 112481, 112500, 112520 + DD 112539, 112558, 112577, 112596, 112615, 112634, 112653, 112672 + DD 112691, 112710, 112729, 112748, 112767, 112786, 112806, 112825 + DD 112844, 112863, 112882, 112901, 112920, 112939, 112958, 112977 + DD 112997, 113016, 113035, 113054, 113073, 113092, 113111, 113130 + DD 113150, 113169, 113188, 113207, 113226, 113245, 113265, 113284 + DD 113303, 113322, 113341, 113360, 113380, 113399, 113418, 113437 + DD 113456, 113476, 113495, 113514, 113533, 113552, 113572, 113591 + DD 113610, 113629, 113649, 113668, 113687, 113706, 113726, 113745 + DD 113764, 113783, 113803, 113822, 113841, 113860, 113880, 113899 + DD 113918, 113937, 113957, 113976, 113995, 114015, 114034, 114053 + DD 114072, 114092, 114111, 114130, 114150, 114169, 114188, 114208 + DD 114227, 114246, 114266, 114285, 114304, 114324, 114343, 114362 + DD 114382, 114401, 114420, 114440, 114459, 114479, 114498, 114517 + DD 114537, 114556, 114575, 114595, 114614, 114634, 114653, 114672 + DD 114692, 114711, 114731, 114750, 114770, 114789, 114808, 114828 + DD 114847, 114867, 114886, 114906, 114925, 114944, 114964, 114983 + DD 115003, 115022, 115042, 115061, 115081, 115100, 115120, 115139 + DD 115159, 115178, 115198, 115217, 115237, 115256, 115276, 115295 + DD 115315, 115334, 115354, 115373, 115393, 115412, 115432, 115451 + DD 115471, 115490, 115510, 115529, 115549, 115569, 115588, 115608 + DD 115627, 115647, 115666, 115686, 115706, 115725, 115745, 115764 + DD 115784, 115804, 115823, 115843, 115862, 115882, 115902, 115921 + DD 115941, 115960, 115980, 116000, 116019, 116039, 116059, 116078 + DD 116098, 116117, 116137, 116157, 116176, 116196, 116216, 116235 + DD 116255, 116275, 116294, 116314, 116334, 116354, 116373, 116393 + DD 116413, 116432, 116452, 116472, 116491, 116511, 116531, 116551 + DD 116570, 116590, 116610, 116630, 116649, 116669, 116689, 116708 + DD 116728, 116748, 116768, 116788, 116807, 116827, 116847, 116867 + DD 116886, 116906, 116926, 116946, 116966, 116985, 117005, 117025 + DD 117045, 117065, 117084, 117104, 117124, 117144, 117164, 117183 + DD 117203, 117223, 117243, 117263, 117283, 117302, 117322, 117342 + DD 117362, 117382, 117402, 117422, 117442, 117461, 117481, 117501 + DD 117521, 117541, 117561, 117581, 117601, 117621, 117640, 117660 + DD 117680, 117700, 117720, 117740, 117760, 117780, 117800, 117820 + DD 117840, 117860, 117880, 117900, 117919, 117939, 117959, 117979 + DD 117999, 118019, 118039, 118059, 118079, 118099, 118119, 118139 + DD 118159, 118179, 118199, 118219, 118239, 118259, 118279, 118299 + DD 118319, 118339, 118359, 118379, 118399, 118419, 118439, 118459 + DD 118480, 118500, 118520, 118540, 118560, 118580, 118600, 118620 + DD 118640, 118660, 118680, 118700, 118720, 118740, 118761, 118781 + DD 118801, 118821, 118841, 118861, 118881, 118901, 118921, 118942 + DD 118962, 118982, 119002, 119022, 119042, 119062, 119083, 119103 + DD 119123, 119143, 119163, 119183, 119204, 119224, 119244, 119264 + DD 119284, 119304, 119325, 119345, 119365, 119385, 119405, 119426 + DD 119446, 119466, 119486, 119506, 119527, 119547, 119567, 119587 + DD 119608, 119628, 119648, 119668, 119689, 119709, 119729, 119749 + DD 119770, 119790, 119810, 119831, 119851, 119871, 119891, 119912 + DD 119932, 119952, 119973, 119993, 120013, 120033, 120054, 120074 + DD 120094, 120115, 120135, 120155, 120176, 120196, 120216, 120237 + DD 120257, 120277, 120298, 120318, 120339, 120359, 120379, 120400 + DD 120420, 120440, 120461, 120481, 120502, 120522, 120542, 120563 + DD 120583, 120604, 120624, 120644, 120665, 120685, 120706, 120726 + DD 120747, 120767, 120787, 120808, 120828, 120849, 120869, 120890 + DD 120910, 120931, 120951, 120971, 120992, 121012, 121033, 121053 + DD 121074, 121094, 121115, 121135, 121156, 121176, 121197, 121217 + DD 121238, 121258, 121279, 121299, 121320, 121341, 121361, 121382 + DD 121402, 121423, 121443, 121464, 121484, 121505, 121525, 121546 + DD 121567, 121587, 121608, 121628, 121649, 121670, 121690, 121711 + DD 121731, 121752, 121773, 121793, 121814, 121834, 121855, 121876 + DD 121896, 121917, 121937, 121958, 121979, 121999, 122020, 122041 + DD 122061, 122082, 122103, 122123, 122144, 122165, 122185, 122206 + DD 122227, 122247, 122268, 122289, 122309, 122330, 122351, 122372 + DD 122392, 122413, 122434, 122454, 122475, 122496, 122517, 122537 + DD 122558, 122579, 122600, 122620, 122641, 122662, 122683, 122703 + DD 122724, 122745, 122766, 122786, 122807, 122828, 122849, 122870 + DD 122890, 122911, 122932, 122953, 122974, 122994, 123015, 123036 + DD 123057, 123078, 123099, 123119, 123140, 123161, 123182, 123203 + DD 123224, 123244, 123265, 123286, 123307, 123328, 123349, 123370 + DD 123391, 123411, 123432, 123453, 123474, 123495, 123516, 123537 + DD 123558, 123579, 123599, 123620, 123641, 123662, 123683, 123704 + DD 123725, 123746, 123767, 123788, 123809, 123830, 123851, 123872 + DD 123893, 123914, 123935, 123956, 123977, 123998, 124019, 124040 + DD 124061, 124081, 124102, 124124, 124145, 124166, 124187, 124208 + DD 124229, 124250, 124271, 124292, 124313, 124334, 124355, 124376 + DD 124397, 124418, 124439, 124460, 124481, 124502, 124523, 124544 + DD 124565, 124586, 124608, 124629, 124650, 124671, 124692, 124713 + DD 124734, 124755, 124776, 124797, 124819, 124840, 124861, 124882 + DD 124903, 124924, 124945, 124967, 124988, 125009, 125030, 125051 + DD 125072, 125093, 125115, 125136, 125157, 125178, 125199, 125221 + DD 125242, 125263, 125284, 125305, 125327, 125348, 125369, 125390 + DD 125411, 125433, 125454, 125475, 125496, 125518, 125539, 125560 + DD 125581, 125603, 125624, 125645, 125666, 125688, 125709, 125730 + DD 125751, 125773, 125794, 125815, 125837, 125858, 125879, 125901 + DD 125922, 125943, 125964, 125986, 126007, 126028, 126050, 126071 + DD 126092, 126114, 126135, 126156, 126178, 126199, 126220, 126242 + DD 126263, 126285, 126306, 126327, 126349, 126370, 126391, 126413 + DD 126434, 126456, 126477, 126498, 126520, 126541, 126563, 126584 + DD 126606, 126627, 126648, 126670, 126691, 126713, 126734, 126756 + DD 126777, 126799, 126820, 126841, 126863, 126884, 126906, 126927 + DD 126949, 126970, 126992, 127013, 127035, 127056, 127078, 127099 + DD 127121, 127142, 127164, 127185, 127207, 127228, 127250, 127271 + DD 127293, 127315, 127336, 127358, 127379, 127401, 127422, 127444 + DD 127465, 127487, 127509, 127530, 127552, 127573, 127595, 127617 + DD 127638, 127660, 127681, 127703, 127725, 127746, 127768, 127789 + DD 127811, 127833, 127854, 127876, 127898, 127919, 127941, 127963 + DD 127984, 128006, 128028, 128049, 128071, 128093, 128114, 128136 + DD 128158, 128179, 128201, 128223, 128244, 128266, 128288, 128309 + DD 128331, 128353, 128375, 128396, 128418, 128440, 128462, 128483 + DD 128505, 128527, 128549, 128570, 128592, 128614, 128636, 128657 + DD 128679, 128701, 128723, 128744, 128766, 128788, 128810, 128832 + DD 128853, 128875, 128897, 128919, 128941, 128963, 128984, 129006 + DD 129028, 129050, 129072, 129094, 129115, 129137, 129159, 129181 + DD 129203, 129225, 129247, 129268, 129290, 129312, 129334, 129356 + DD 129378, 129400, 129422, 129444, 129465, 129487, 129509, 129531 + DD 129553, 129575, 129597, 129619, 129641, 129663, 129685, 129707 + DD 129729, 129751, 129773, 129794, 129816, 129838, 129860, 129882 + DD 129904, 129926, 129948, 129970, 129992, 130014, 130036, 130058 + DD 130080, 130102, 130124, 130146, 130168, 130190, 130212, 130235 + DD 130257, 130279, 130301, 130323, 130345, 130367, 130389, 130411 + DD 130433, 130455, 130477, 130499, 130521, 130543, 130566, 130588 + DD 130610, 130632, 130654, 130676, 130698, 130720, 130742, 130765 + DD 130787, 130809, 130831, 130853, 130875, 130897, 130920, 130942 + DD 130964, 130986, 131008, 131030, 131053, 131075, 131097, 131119 + DD 131141, 131163, 131186, 131208, 131230, 131252, 131274, 131297 + DD 131319, 131341, 131363, 131386, 131408, 131430, 131452, 131475 + DD 131497, 131519, 131541, 131564, 131586, 131608, 131630, 131653 + DD 131675, 131697, 131720, 131742, 131764, 131786, 131809, 131831 + DD 131853, 131876, 131898, 131920, 131943, 131965, 131987, 132010 + DD 132032, 132054, 132077, 132099, 132121, 132144, 132166, 132188 + DD 132211, 132233, 132256, 132278, 132300, 132323, 132345, 132368 + DD 132390, 132412, 132435, 132457, 132480, 132502, 132524, 132547 + DD 132569, 132592, 132614, 132637, 132659, 132682, 132704, 132726 + DD 132749, 132771, 132794, 132816, 132839, 132861, 132884, 132906 + DD 132929, 132951, 132974, 132996, 133019, 133041, 133064, 133086 + DD 133109, 133131, 133154, 133176, 133199, 133221, 133244, 133267 + DD 133289, 133312, 133334, 133357, 133379, 133402, 133425, 133447 + DD 133470, 133492, 133515, 133537, 133560, 133583, 133605, 133628 + DD 133651, 133673, 133696, 133718, 133741, 133764, 133786, 133809 + DD 133832, 133854, 133877, 133900, 133922, 133945, 133968, 133990 + DD 134013, 134036, 134058, 134081, 134104, 134126, 134149, 134172 + DD 134194, 134217, 134240, 134263, 134285, 134308, 134331, 134353 + DD 134376, 134399, 134422, 134444, 134467, 134490, 134513, 134535 + DD 134558, 134581, 134604, 134627, 134649, 134672, 134695, 134718 + DD 134741, 134763, 134786, 134809, 134832, 134855, 134877, 134900 + DD 134923, 134946, 134969, 134992, 135014, 135037, 135060, 135083 + DD 135106, 135129, 135152, 135174, 135197, 135220, 135243, 135266 + DD 135289, 135312, 135335, 135358, 135381, 135403, 135426, 135449 + DD 135472, 135495, 135518, 135541, 135564, 135587, 135610, 135633 + DD 135656, 135679, 135702, 135725, 135748, 135771, 135794, 135816 + DD 135839, 135862, 135885, 135908, 135931, 135954, 135977, 136000 + DD 136023, 136047, 136070, 136093, 136116, 136139, 136162, 136185 + DD 136208, 136231, 136254, 136277, 136300, 136323, 136346, 136369 + DD 136392, 136415, 136438, 136462, 136485, 136508, 136531, 136554 + DD 136577, 136600, 136623, 136646, 136670, 136693, 136716, 136739 + DD 136762, 136785, 136808, 136832, 136855, 136878, 136901, 136924 + DD 136947, 136971, 136994, 137017, 137040, 137063, 137086, 137110 + DD 137133, 137156, 137179, 137203, 137226, 137249, 137272, 137295 + DD 137319, 137342, 137365, 137388, 137412, 137435, 137458, 137481 + DD 137505, 137528, 137551, 137575, 137598, 137621, 137644, 137668 + DD 137691, 137714, 137738, 137761, 137784, 137808, 137831, 137854 + DD 137877, 137901, 137924, 137948, 137971, 137994, 138018, 138041 + DD 138064, 138088, 138111, 138134, 138158, 138181, 138205, 138228 + DD 138251, 138275, 138298, 138322, 138345, 138368, 138392, 138415 + DD 138439, 138462, 138485, 138509, 138532, 138556, 138579, 138603 + DD 138626, 138650, 138673, 138697, 138720, 138744, 138767, 138790 + DD 138814, 138837, 138861, 138884, 138908, 138931, 138955, 138978 + DD 139002, 139026, 139049, 139073, 139096, 139120, 139143, 139167 + DD 139190, 139214, 139237, 139261, 139285, 139308, 139332, 139355 + DD 139379, 139402, 139426, 139450, 139473, 139497, 139520, 139544 + DD 139568, 139591, 139615, 139639, 139662, 139686, 139709, 139733 + DD 139757, 139780, 139804, 139828, 139851, 139875, 139899, 139922 + DD 139946, 139970, 139993, 140017, 140041, 140065, 140088, 140112 + DD 140136, 140159, 140183, 140207, 140231, 140254, 140278, 140302 + DD 140326, 140349, 140373, 140397, 140421, 140444, 140468, 140492 + DD 140516, 140539, 140563, 140587, 140611, 140635, 140658, 140682 + DD 140706, 140730, 140754, 140777, 140801, 140825, 140849, 140873 + DD 140897, 140920, 140944, 140968, 140992, 141016, 141040, 141064 + DD 141087, 141111, 141135, 141159, 141183, 141207, 141231, 141255 + DD 141279, 141303, 141326, 141350, 141374, 141398, 141422, 141446 + DD 141470, 141494, 141518, 141542, 141566, 141590, 141614, 141638 + DD 141662, 141686, 141710, 141734, 141758, 141782, 141806, 141830 + DD 141854, 141878, 141902, 141926, 141950, 141974, 141998, 142022 + DD 142046, 142070, 142094, 142118, 142142, 142166, 142190, 142214 + DD 142238, 142262, 142286, 142310, 142334, 142359, 142383, 142407 + DD 142431, 142455, 142479, 142503, 142527, 142551, 142576, 142600 + DD 142624, 142648, 142672, 142696, 142720, 142745, 142769, 142793 + DD 142817, 142841, 142865, 142890, 142914, 142938, 142962, 142986 + DD 143011, 143035, 143059, 143083, 143107, 143132, 143156, 143180 + DD 143204, 143228, 143253, 143277, 143301, 143325, 143350, 143374 + DD 143398, 143423, 143447, 143471, 143495, 143520, 143544, 143568 + DD 143593, 143617, 143641, 143665, 143690, 143714, 143738, 143763 + DD 143787, 143811, 143836, 143860, 143884, 143909, 143933, 143957 + DD 143982, 144006, 144031, 144055, 144079, 144104, 144128, 144152 + DD 144177, 144201, 144226, 144250, 144275, 144299, 144323, 144348 + DD 144372, 144397, 144421, 144446, 144470, 144494, 144519, 144543 + DD 144568, 144592, 144617, 144641, 144666, 144690, 144715, 144739 + DD 144764, 144788, 144813, 144837, 144862, 144886, 144911, 144935 + DD 144960, 144984, 145009, 145033, 145058, 145082, 145107, 145132 + DD 145156, 145181, 145205, 145230, 145254, 145279, 145304, 145328 + DD 145353, 145377, 145402, 145427, 145451, 145476, 145500, 145525 + DD 145550, 145574, 145599, 145624, 145648, 145673, 145698, 145722 + DD 145747, 145772, 145796, 145821, 145846, 145870, 145895, 145920 + DD 145944, 145969, 145994, 146018, 146043, 146068, 146093, 146117 + DD 146142, 146167, 146191, 146216, 146241, 146266, 146290, 146315 + DD 146340, 146365, 146390, 146414, 146439, 146464, 146489, 146513 + DD 146538, 146563, 146588, 146613, 146637, 146662, 146687, 146712 + DD 146737, 146762, 146786, 146811, 146836, 146861, 146886, 146911 + DD 146936, 146960, 146985, 147010, 147035, 147060, 147085, 147110 + DD 147135, 147160, 147184, 147209, 147234, 147259, 147284, 147309 + DD 147334, 147359, 147384, 147409, 147434, 147459, 147484, 147509 + DD 147534, 147559, 147583, 147608, 147633, 147658, 147683, 147708 + DD 147733, 147758, 147783, 147808, 147833, 147858, 147883, 147909 + DD 147934, 147959, 147984, 148009, 148034, 148059, 148084, 148109 + DD 148134, 148159, 148184, 148209, 148234, 148259, 148284, 148310 + DD 148335, 148360, 148385, 148410, 148435, 148460, 148485, 148510 + DD 148536, 148561, 148586, 148611, 148636, 148661, 148686, 148712 + DD 148737, 148762, 148787, 148812, 148838, 148863, 148888, 148913 + DD 148938, 148964, 148989, 149014, 149039, 149064, 149090, 149115 + DD 149140, 149165, 149191, 149216, 149241, 149266, 149292, 149317 + DD 149342, 149367, 149393, 149418, 149443, 149469, 149494, 149519 + DD 149544, 149570, 149595, 149620, 149646, 149671, 149696, 149722 + DD 149747, 149772, 149798, 149823, 149848, 149874, 149899, 149925 + DD 149950, 149975, 150001, 150026, 150051, 150077, 150102, 150128 + DD 150153, 150178, 150204, 150229, 150255, 150280, 150306, 150331 + DD 150356, 150382, 150407, 150433, 150458, 150484, 150509, 150535 + DD 150560, 150586, 150611, 150637, 150662, 150688, 150713, 150739 + DD 150764, 150790, 150815, 150841, 150866, 150892, 150917, 150943 + DD 150968, 150994, 151019, 151045, 151071, 151096, 151122, 151147 + DD 151173, 151198, 151224, 151250, 151275, 151301, 151326, 151352 + DD 151378, 151403, 151429, 151455, 151480, 151506, 151531, 151557 + DD 151583, 151608, 151634, 151660, 151685, 151711, 151737, 151762 + DD 151788, 151814, 151839, 151865, 151891, 151917, 151942, 151968 + DD 151994, 152019, 152045, 152071, 152097, 152122, 152148, 152174 + DD 152200, 152225, 152251, 152277, 152303, 152328, 152354, 152380 + DD 152406, 152432, 152457, 152483, 152509, 152535, 152561, 152586 + DD 152612, 152638, 152664, 152690, 152716, 152741, 152767, 152793 + DD 152819, 152845, 152871, 152897, 152922, 152948, 152974, 153000 + DD 153026, 153052, 153078, 153104, 153130, 153156, 153181, 153207 + DD 153233, 153259, 153285, 153311, 153337, 153363, 153389, 153415 + DD 153441, 153467, 153493, 153519, 153545, 153571, 153597, 153623 + DD 153649, 153675, 153701, 153727, 153753, 153779, 153805, 153831 + DD 153857, 153883, 153909, 153935, 153961, 153987, 154013, 154039 + DD 154065, 154091, 154118, 154144, 154170, 154196, 154222, 154248 + DD 154274, 154300, 154326, 154352, 154379, 154405, 154431, 154457 + DD 154483, 154509, 154535, 154562, 154588, 154614, 154640, 154666 + DD 154692, 154719, 154745, 154771, 154797, 154823, 154850, 154876 + DD 154902, 154928, 154954, 154981, 155007, 155033, 155059, 155086 + DD 155112, 155138, 155164, 155191, 155217, 155243, 155269, 155296 + DD 155322, 155348, 155374, 155401, 155427, 155453, 155480, 155506 + DD 155532, 155559, 155585, 155611, 155638, 155664, 155690, 155717 + DD 155743, 155769, 155796, 155822, 155848, 155875, 155901, 155928 + DD 155954, 155980, 156007, 156033, 156060, 156086, 156112, 156139 + DD 156165, 156192, 156218, 156245, 156271, 156297, 156324, 156350 + DD 156377, 156403, 156430, 156456, 156483, 156509, 156536, 156562 + DD 156589, 156615, 156642, 156668, 156695, 156721, 156748, 156774 + DD 156801, 156827, 156854, 156880, 156907, 156934, 156960, 156987 + DD 157013, 157040, 157066, 157093, 157120, 157146, 157173, 157199 + DD 157226, 157253, 157279, 157306, 157332, 157359, 157386, 157412 + DD 157439, 157466, 157492, 157519, 157546, 157572, 157599, 157626 + DD 157652, 157679, 157706, 157732, 157759, 157786, 157812, 157839 + DD 157866, 157893, 157919, 157946, 157973, 157999, 158026, 158053 + DD 158080, 158106, 158133, 158160, 158187, 158213, 158240, 158267 + DD 158294, 158321, 158347, 158374, 158401, 158428, 158455, 158481 + DD 158508, 158535, 158562, 158589, 158616, 158642, 158669, 158696 + DD 158723, 158750, 158777, 158804, 158830, 158857, 158884, 158911 + DD 158938, 158965, 158992, 159019, 159046, 159073, 159100, 159126 + DD 159153, 159180, 159207, 159234, 159261, 159288, 159315, 159342 + DD 159369, 159396, 159423, 159450, 159477, 159504, 159531, 159558 + DD 159585, 159612, 159639, 159666, 159693, 159720, 159747, 159774 + DD 159801, 159828, 159855, 159882, 159909, 159936, 159963, 159990 + DD 160018, 160045, 160072, 160099, 160126, 160153, 160180, 160207 + DD 160234, 160261, 160289, 160316, 160343, 160370, 160397, 160424 + DD 160451, 160479, 160506, 160533, 160560, 160587, 160614, 160642 + DD 160669, 160696, 160723, 160750, 160778, 160805, 160832, 160859 + DD 160886, 160914, 160941, 160968, 160995, 161023, 161050, 161077 + DD 161104, 161132, 161159, 161186, 161213, 161241, 161268, 161295 + DD 161323, 161350, 161377, 161405, 161432, 161459, 161487, 161514 + DD 161541, 161569, 161596, 161623, 161651, 161678, 161705, 161733 + DD 161760, 161787, 161815, 161842, 161870, 161897, 161924, 161952 + DD 161979, 162007, 162034, 162061, 162089, 162116, 162144, 162171 + DD 162199, 162226, 162253, 162281, 162308, 162336, 162363, 162391 + DD 162418, 162446, 162473, 162501, 162528, 162556, 162583, 162611 + DD 162638, 162666, 162693, 162721, 162748, 162776, 162804, 162831 + DD 162859, 162886, 162914, 162941, 162969, 162997, 163024, 163052 + DD 163079, 163107, 163135, 163162, 163190, 163217, 163245, 163273 + DD 163300, 163328, 163356, 163383, 163411, 163438, 163466, 163494 + DD 163521, 163549, 163577, 163604, 163632, 163660, 163688, 163715 + DD 163743, 163771, 163798, 163826, 163854, 163882, 163909, 163937 + DD 163965, 163993, 164020, 164048, 164076, 164104, 164131, 164159 + DD 164187, 164215, 164243, 164270, 164298, 164326, 164354, 164382 + DD 164409, 164437, 164465, 164493, 164521, 164549, 164576, 164604 + DD 164632, 164660, 164688, 164716, 164744, 164771, 164799, 164827 + DD 164855, 164883, 164911, 164939, 164967, 164995, 165023, 165051 + DD 165078, 165106, 165134, 165162, 165190, 165218, 165246, 165274 + DD 165302, 165330, 165358, 165386, 165414, 165442, 165470, 165498 + DD 165526, 165554, 165582, 165610, 165638, 165666, 165694, 165722 + DD 165750, 165778, 165806, 165834, 165862, 165891, 165919, 165947 + DD 165975, 166003, 166031, 166059, 166087, 166115, 166143, 166172 + DD 166200, 166228, 166256, 166284, 166312, 166340, 166368, 166397 + DD 166425, 166453, 166481, 166509, 166538, 166566, 166594, 166622 + DD 166650, 166678, 166707, 166735, 166763, 166791, 166820, 166848 + DD 166876, 166904, 166933, 166961, 166989, 167017, 167046, 167074 + DD 167102, 167130, 167159, 167187, 167215, 167244, 167272, 167300 + DD 167328, 167357, 167385, 167413, 167442, 167470, 167498, 167527 + DD 167555, 167584, 167612, 167640, 167669, 167697, 167725, 167754 + DD 167782, 167811, 167839, 167867, 167896, 167924, 167953, 167981 + DD 168009, 168038, 168066, 168095, 168123, 168152, 168180, 168209 + DD 168237, 168266, 168294, 168322, 168351, 168379, 168408, 168436 + DD 168465, 168493, 168522, 168551, 168579, 168608, 168636, 168665 + DD 168693, 168722, 168750, 168779, 168807, 168836, 168865, 168893 + DD 168922, 168950, 168979, 169007, 169036, 169065, 169093, 169122 + DD 169151, 169179, 169208, 169236, 169265, 169294, 169322, 169351 + DD 169380, 169408, 169437, 169466, 169494, 169523, 169552, 169580 + DD 169609, 169638, 169667, 169695, 169724, 169753, 169781, 169810 + DD 169839, 169868, 169896, 169925, 169954, 169983, 170011, 170040 + DD 170069, 170098, 170127, 170155, 170184, 170213, 170242, 170271 + DD 170299, 170328, 170357, 170386, 170415, 170444, 170472, 170501 + DD 170530, 170559, 170588, 170617, 170646, 170674, 170703, 170732 + DD 170761, 170790, 170819, 170848, 170877, 170906, 170935, 170964 + DD 170992, 171021, 171050, 171079, 171108, 171137, 171166, 171195 + DD 171224, 171253, 171282, 171311, 171340, 171369, 171398, 171427 + DD 171456, 171485, 171514, 171543, 171572, 171601, 171630, 171659 + DD 171688, 171717, 171746, 171776, 171805, 171834, 171863, 171892 + DD 171921, 171950, 171979, 172008, 172037, 172066, 172096, 172125 + DD 172154, 172183, 172212, 172241, 172270, 172300, 172329, 172358 + DD 172387, 172416, 172445, 172475, 172504, 172533, 172562, 172591 + DD 172621, 172650, 172679, 172708, 172737, 172767, 172796, 172825 + DD 172854, 172884, 172913, 172942, 172972, 173001, 173030, 173059 + DD 173089, 173118, 173147, 173177, 173206, 173235, 173264, 173294 + DD 173323, 173352, 173382, 173411, 173440, 173470, 173499, 173529 + DD 173558, 173587, 173617, 173646, 173675, 173705, 173734, 173764 + DD 173793, 173822, 173852, 173881, 173911, 173940, 173970, 173999 + DD 174028, 174058, 174087, 174117, 174146, 174176, 174205, 174235 + DD 174264, 174294, 174323, 174353, 174382, 174412, 174441, 174471 + DD 174500, 174530, 174559, 174589, 174618, 174648, 174678, 174707 + DD 174737, 174766, 174796, 174825, 174855, 174885, 174914, 174944 + DD 174973, 175003, 175033, 175062, 175092, 175122, 175151, 175181 + DD 175210, 175240, 175270, 175299, 175329, 175359, 175388, 175418 + DD 175448, 175478, 175507, 175537, 175567, 175596, 175626, 175656 + DD 175686, 175715, 175745, 175775, 175804, 175834, 175864, 175894 + DD 175924, 175953, 175983, 176013, 176043, 176072, 176102, 176132 + DD 176162, 176192, 176221, 176251, 176281, 176311, 176341, 176371 + +GUSScreenList Label + DW 7 + DW Near Ptr IdleFunctionList + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr GravisHeaderLine + + DW Near Ptr MixerText + DW Near Ptr VolumeBox1 + DW Near Ptr VolumeBox2 + + DW Near Ptr MasterVolumeLeft ; 7 + DW Near Ptr MasterVolumeRight + DW Near Ptr TrebleVolumeLeft + DW Near Ptr TrebleVolumeRight + DW Near Ptr BassVolumeLeft + DW Near Ptr BassVolumeRight ; 12 + + DW Near Ptr SampleText + + DW Near Ptr SampleSize0Button ; 14 + DW Near Ptr SampleSize1Button + DW Near Ptr SampleSize2Button + DW Near Ptr SampleSize3Button ; 17 + + DW Near Ptr EffectText + DW Near Ptr EffectBox + + DW Near Ptr ChorusThumbBar ; 20 + DW Near Ptr ReverbThumbBar + + DW DriverText + + DW 0 + +GravisHeaderLine DW 10 + DB "Sound Blaster AWE 32 Driver", 0 + +DriverText DW 1 + DB 27, 48 + DB 21h + DB "Sound Blaster AWE 32 Driver 1.5 for Impulse Tracker", 0 + +MixerText DW 1 + DB 3, 13 + DB 20h + DB "Mixer options", 13 + DB 13 + DB " Master Volume Left", 13 + DB " Master Volume Right", 13 + DB 13 + DB 13 + DB " Treble Left", 13 + DB " Treble Right", 13 + DB " Bass Left", 13 + DB " Bass Right", 13 + DB 0 + +VolumeBox1 DW 0 + DB 24, 14, 30, 17 + DB 25 + +VolumeBox2 DW 0 + DB 17, 18, 21, 23 + DB 25 + +MasterVolumeLeft DW 9 + DB 25, 15 + DW 0, 31 + DW 9, 0 + DW 0FFFFh, 8, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +MasterVolumeRight DW 9 + DB 25, 16 + DW 0, 31 + DW 9, 1 + DW 7, 9, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +TrebleVolumeLeft DW 9 + DB 18, 19 + DW 0, 15 + DW 9, 2 + DW 8, 10, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +TrebleVolumeRight DW 9 + DB 18, 20 + DW 0, 15 + DW 9, 3 + DW 9, 11, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +BassVolumeLeft DW 9 + DB 18, 21 + DW 0, 15 + DW 9, 4 + DW 10, 12, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +BassVolumeRight DW 9 + DB 18, 22 + DW 0, 15 + DW 9, 5 + DW 11, 14, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +SampleText DW 1 + DB 3, 25 + DB 20h + DB "Sample resizing options", 0 + +SampleSize0Button DW 2 + DW 12, 15, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetCompress +DriverSegment1 DW 0 + DW 0 + DW Offset SetCompress +DriverSegment2 DW 0 + DB 7, 27, 20, 29, 8 + DB 0 + DB " Original", 0 + +SampleSize1Button DW 2 + DW 14, 16, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetCompress +DriverSegment3 DW 0 + DW 1 + DW Offset SetCompress +DriverSegment4 DW 0 + DB 7, 30, 20, 32, 8 + DB 0 + DB " Half", 0 + +SampleSize2Button DW 2 + DW 15, 17, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetCompress +DriverSegment5 DW 0 + DW 2 + DW Offset SetCompress +DriverSegment6 DW 0 + DB 7, 33, 20, 35, 8 + DB 0 + DB " Quarter", 0 + +SampleSize3Button DW 2 + DW 16, 20, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetCompress +DriverSegment7 DW 0 + DW 3 + DW Offset SetCompress +DriverSegment8 DW 0 + DB 7, 36, 20, 38, 8 + DB 0 + DB " Eighth", 0 + +EffectText DW 1 + DB 3, 40 + DB 20h + DB "Effect options", 13 + DB 13 + DB " Chorus", 13 + DB " Reverb", 0 + + +EffectBox DW 0 + DB 12, 41, 30, 44 + DB 25 + +ChorusThumbBar DW 9 + DB 13, 42 + DW 0, 127 + DW 9, 6 + DW 17, 21, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +ReverbThumbBar DW 9 + DB 13, 43 + DW 0, 127 + DW 9, 7 + DW 20, 0FFFFh, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + + + +VolumeTable DB 6 Dup (0) +CONFIGURATIONOFFSET EQU $+128 +CONFIGSIZE EQU 2 +Chorus DB 10, 64 + +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +IdleFunctionList DD 0 + DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +AWEParameters DB 64 Dup (0FFh), 64 Dup (0) + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SBOut ; AL = data + ; DX = 2xCh + + Push AX + +SBOut1: + In AL, DX + Test AL, AL + JS SBOut1 + + Pop AX + Out DX, AL + + Ret + +EndP SBOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectUART ; Given DX = Port + +; From SB-DevKit + + ClI + + Inc DX + Xor CX, CX + +DetectUART1: + In AL, DX + Test AL, 40h ; Ready for output + LoopNZ DetectUART1 + JNZ DetectUARTError + + Mov AL, 0FFh ; Reset! + Out DX, AL + + Xor CX, CX + +DetectUART2: + In AL, DX + Test AL, 80h + JNZ DetectUART3 + + Dec DX + In AL, DX + Inc DX + Cmp AL, 0FEh + JE DetectUART4 + +DetectUART3: + Loop DetectUART2 + +DetectUARTError: + StI + StC + Ret + +DetectUART4: ; Now to shove it into 'intelligent' mode. + Xor CX, CX + +DetectUART5: + In AL, DX + Test AL, 40h + LoopNZ DetectUART5 + JNZ DetectUARTError + + Mov AL, 3Fh ; Intelligent mode! + Out DX, AL + +DetectUART6: + Xor CX, CX + +DetectUART7: + In AL, DX + Test AL, 80h + JNZ DetectUART8 + + Dec DX + In AL, DX + Inc DX + Cmp AL, 0FEh + JE DetectUART9 + +DetectUART8: + Loop DetectUART7 + + Jmp DetectUARTError + +DetectUART9: + StI + ClC + Ret + +EndP DetectUART + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReinitUART + + Mov DX, MIDIPort + Test DX, DX + JZ ReinitUART1 + + Call DetectUART + +ReinitUART1: + Ret + +EndP ReinitUART + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetUART + + Mov DX, MIDIPort + Test DX, DX + JZ ResetUART1 + + Inc DX + + Mov AL, 0FFh + Out DX, AL + +ResetUART1: + Ret + +EndP ResetUART + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetCompress Far + + Mov CX, [SI+22] + Mov CS:Compress, CL + + Mov AX, 1 + ShL AX, CL + Mov CS:Step, AX + + Call Music_LoadAllSamples + + Mov AX, 1 + Ret + +EndP SetCompress + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetCompress Far + + Push CS + Pop ES + Mov DI, Offset Compress + + Ret + +EndP GetCompress + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Load8BitSamplesForwards ; Given DS:SI, ECX = count + + Push BX + + Mov BX, CS:Step + Mov DX, CS:BasePort + Add DX, 400h + Xor AL, AL + +Load8BitSamplesForwards2: + Mov AH, [SI] + Add SI, BX + JC Load8BitSamplesForwards4 + +Load8BitSamplesForwards3: + Out DX, AX + + Dec ECX + JNZ Load8BitSamplesForwards2 + + Pop BX + Ret + +Load8BitSamplesForwards4: + Add ESI, 10000h + Int 3 + Jmp Load8BitSamplesForwards3 + +EndP Load8BitSamplesForwards + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Load16BitSamplesForwards ; Given DS:SI, ECX = count + + Push BX + + Mov BX, CS:Step + Mov DX, CS:BasePort + Add DX, 400h + Add BX, BX + +Load16BitSamplesForwards2: + Mov AX, [SI] + Add SI, BX + JC Load16BitSamplesForwards4 + +Load16BitSamplesForwards3: + Out DX, AX + + Dec ECX + JNZ Load16BitSamplesForwards2 + + Pop BX + Ret + +Load16BitSamplesForwards4: + Add ESI, 10000h + Int 3 + Jmp Load16BitSamplesForwards3 + +EndP Load16BitSamplesForwards + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Load8BitSamplesBackwards ; Given DS:SI, ECX = count + + Push BX + + Mov BX, CS:Step + Mov DX, CS:BasePort + Add DX, 400h + Xor AL, AL + + Sub SI, BX + JC Load8BitSamplesBackwards6 + +Load8BitSamplesBackwards2: + Sub SI, BX + JC Load8BitSamplesBackwards4 + +Load8BitSamplesBackwards3: + Mov AH, [SI] + Out DX, AX + + Dec ECX + JNZ Load8BitSamplesBackwards2 + + + Pop BX + Ret + +Load8BitSamplesBackwards4: + Sub ESI, 10000h + JC Load8BitSamplesBackwards5 + Int 3 + Jmp Load8BitSamplesBackwards3 + +Load8BitSamplesBackwards5: + Xor ESI, ESI + Jmp Load8BitSamplesBackwards3 + +Load8BitSamplesBackwards6: + Sub ESI, 10000h + Int 3 + Jmp Load8BitSamplesBackwards2 + + +EndP Load8BitSamplesBackwards + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Load16BitSamplesBackwards ; Given DS:SI, ECX = count + + Push BX + + Mov BX, CS:Step + Mov DX, CS:BasePort + Add DX, 400h + Add BX, BX + + Sub SI, BX + JC Load16BitSamplesBackwards6 + +Load16BitSamplesBackwards2: + Sub SI, BX + JC Load16BitSamplesBackwards4 + +Load16BitSamplesBackwards3: + Mov AX, [SI] + Out DX, AX + + Dec ECX + JNZ Load16BitSamplesBackwards2 + + Pop BX + Ret + +Load16BitSamplesBackwards4: + Sub ESI, 10000h + JC Load16BitSamplesBackwards5 + Int 3 + Jmp Load16BitSamplesBackwards3 + +Load16BitSamplesBackwards5: + Xor ESI, ESI + Jmp Load16BitSamplesBackwards3 + +Load16BitSamplesBackwards6: + Sub ESI, 10000h + Int 3 + Jmp Load16BitSamplesBackwards2 + + +EndP Load16BitSamplesBackwards + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WriteDataChannel + + Or AX, DX + +Proc WriteData ; Have BX/EBX = value + ; AX = xxyyh + ; ^ ^ + ; | | + ; | \-- value to send to pointer register + ; \---- 0, 1, 2 or 3, 4 + ; 0 = data reg 0 + ; 1 = data reg 1, dword + ; 2 = data reg 2 + ; 3 = data reg 3 + ; 4 = data reg 4, word + + Push DX + Push AX + + Mov DX, BasePort + Add DX, 802h + And AX, 0FFh + Out DX, AX + Pop AX + + Cmp AH, 1 + JB WriteDataReg0 + JE WriteDataReg1DWord + Cmp AH, 3 + JB WriteDataReg2 + JE WriteDataReg3 + Jmp WriteDataReg1Word + +WriteDataReg0: + Sub DX, 802h + Mov EAX, EBX + Out DX, EAX + + Pop DX + Ret + +WriteDataReg1DWord: + Sub DX, 402h + Mov EAX, EBX + Out DX, EAX + + Pop DX + Ret + +WriteDataReg1Word: + Sub DX, 402h + Mov AX, BX + Out DX, AX + + Pop DX + Ret + +WriteDataReg2: + Sub DX, 400h + Mov AX, BX + Out DX, AX + + Pop DX + Ret + +WriteDataReg3: + Sub DL, 2 + Mov AX, BX + Out DX, AX + + Pop DX + Ret + +EndP WriteData + +EndP WriteDataChannel + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReadDataChannel + + Or AX, DX + +Proc ReadData ; AX = xxyyh + ; ^ ^ + ; | | + ; | \-- value to send to pointer register + ; \---- 0, 1, 2 or 3, 4 + ; 0 = data reg 0 + ; 1 = data reg 1, dword + ; 2 = data reg 2 + ; 3 = data reg 3 + ; 4 = data reg 4, word + + Push DX + Push AX + + Mov DX, BasePort + Add DX, 802h + And AX, 0FFh + Out DX, AX + Pop AX + + Cmp AH, 1 + JB ReadDataReg0 + JE ReadDataReg1DWord + Cmp AH, 3 + JB ReadDataReg2 + JE ReadDataReg3 + Jmp ReadDataReg1Word + +ReadDataReg0: + Sub DX, 802h + In EAX, DX + + Pop DX + Ret + +ReadDataReg1DWord: + Sub DX, 402h + In EAX, DX + + Pop DX + Ret + +ReadDataReg1Word: + Sub DX, 402h + In AX, DX + + Pop DX + Ret + +ReadDataReg2: + Sub DX, 400h + In AX, DX + + Pop DX + Ret + +ReadDataReg3: + Sub DL, 2 + In AX, DX + + Pop DX + Ret + +EndP ReadData + +EndP ReadDataChannel + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetAWEFrequency + + Push DS + Push SI + Push CX + Push DX + + Mov EAX, [SI+10h] ; Final freq + + Mov CL, Compress + ShR EAX, CL + + Test EAX, EAX + JZ SetAWEFrequencyError + Cmp EAX, 88200*2 + JAE SetAWEFrequencyError + + Push CS + Pop DS + Assume DS:Driver + + And ESI, 0FFFFh + + Mov BX, 0F000h + Mov CX, 0FFFh ; Use binary search + Xor DX, DX ; CX = upper, DX = lower + +SetAWEFrequency1: + Cmp EAX, 88200 + JAE SetAWEFrequency2 + + Sub BX, 1000h + JC SetAWEFrequencyError + Add EAX, EAX + Jmp SetAWEFrequency1 + +SetAWEFrequency2: + Cmp CX, DX + JBE SetAWEFrequency5 + + Mov SI, CX + Add SI, DX + ShR SI, 1 + + Cmp EAX, [AWEPitchTable+ESI*4] + JE SetAWEFrequency3 + JB SetAWEFrequency4 ; In lower half + + ; In upper half + Inc SI + Mov DX, SI + Jmp SetAWEFrequency2 + +SetAWEFrequency4: ; In lower half + Dec SI + Mov CX, SI + Jmp SetAWEFrequency2 + +SetAWEFrequency5: + Mov SI, CX + +SetAWEFrequency3: + Add BX, SI + + Pop DX + Pop CX + Pop SI + Pop DS + + Mov AX, IP + Call WriteDataChannel + + Ret + Assume DS:Nothing + +SetAWEFrequencyError: + Call StopAWENote + + Mov Word Ptr [SI], 200h + Test Byte Ptr [SI+3Ah], 80h + JNZ SetAWEFrequencyError1 + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Signify channel off + +SetAWEFrequencyError1: + Mov AX, IP + Xor EBX, EBX + Call WriteDataChannel + + Push CS + Pop DS + Mov SI, Offset FrequencyError + Mov BX, 40 + Call SetInfoLine + + Pop DX + Pop CX + Pop SI + Pop DS + + Ret + +EndP SetAWEFrequency + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetAWEPan + + Mov AX, PSST + Call ReadDataChannel ; Get starting offset + + Cmp CS:Stereo, 0 + JE SetPan2 + + Test CL, 128 + JNZ SetPan2 + + Mov BL, [SI+37h] ; Final pan + Cmp BL, 100 ; Surround -> central + JNE SetPan1 + +SetPan2: + Mov BL, 32 + +SetPan1: ; BL = 0->64, need to extend to 0->255 + Add BL, BL + Add BL, BL + SBB BL, 0 ; BL = 0->255 + Not BL + + ShL EAX, 8 + SHLD EBX, EAX, 24 + Mov AX, PSST + Call WriteDataChannel + + Ret + +EndP SetAWEPan + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetAWEVolume + + Test CH, 8 + JZ SetAWEVolume1 + + Test CH, 1 + JNZ SetAWEVolume5 + + Cmp Byte Ptr [SI+8], 0FFh + JE SetAWEVolume4 + +SetAWEVolume5: + Mov Byte Ptr [SI+8], 0FFh + + Mov AX, IFATN + Call ReadDataChannel + Mov BX, AX + Mov AX, IFATN + Mov BL, 0FFh + Call WriteDataChannel + +SetAWEVolume4: + Ret + +SetAWEVolume1: +; First check if channel has been disowned + Xor BX, BX + Mov BL, [SI+3Ah] ; BL = host channel + + Test BL, BL + JS SetAWEVolume3 + +SetAWEVolume2: + Mov AH, [CS:AWEParameters+BX] ; AH = filter + Mov AL, [CS:AWEParameters+BX+64] ; AL = Q. + + ShR AL, 3 + Mov [SI+5Bh], AH + + Cmp AL, [SI+3Fh] + JE SetAWEVolume3 + + Mov [SI+3Fh], AL + +; Set Q + Mov BL, AL + ShL EBX, 28 + + Mov AX, CCCA + Call ReadDataChannel + And EAX, 0FFFFFFFh + Or EBX, EAX + Mov AX, CCCA + Call WriteDataChannel + +SetAWEVolume3: + Mov AL, [SI+3Eh] + Mul Byte Ptr [SI+5Bh] + ShL AX, 1 + Xor BX, BX + Add AH, 1 + Mov BL, [SI+20h] ; Final volume + Mov [SI+8], BL + Mov BL, [CS:AWEVolumeTable+BX] + Mov BH, AH + Mov AX, IFATN + Call WriteDataChannel + + Ret + +EndP SetAWEVolume + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StopAWENote + + Mov AX, DCYSUSV + Mov BX, 80h + Call WriteDataChannel + + Mov AX, VTFT + Mov EBX, 0FFFFh + Call WriteDataChannel + + Mov AX, CVCF + Call WriteDataChannel + + Mov BX, 80h + Mov AX, DCYSUSV + Call WriteDataChannel + + Mov AX, VTFT + Mov EBX, 0FFFFh + Call WriteDataChannel + + Mov AX, CVCF + Call WriteDataChannel + + Xor EBX, EBX + Mov AX, ENVVOL + Call WriteDataChannel + + Mov AX, ENVVAL + Call WriteDataChannel + + Mov AX, SUSDCY + Call WriteDataChannel + + Mov AX, ATKHLDV + Call WriteDataChannel + + Mov AX, LFO1VAL + Call WriteDataChannel + + Mov AX, HLDATK + Call WriteDataChannel + + Mov AX, LFO2VAL + Call WriteDataChannel + + Mov AX, IP + Call WriteDataChannel + + Mov AX, IFATN + Call WriteDataChannel + + Mov AX, PEFE + Call WriteDataChannel + + Mov AX, FMMOD + Call WriteDataChannel + + Mov AX, TREMFRQ + Call WriteDataChannel + + Mov AX, FM2FRQ2 + Call WriteDataChannel + + Mov AX, PTRX + Call WriteDataChannel + + Mov AX, VTFT + Call WriteDataChannel + +; Mov AX, PSST +; Call WriteDataChannel + + Mov BL, 8 + Mov AX, CSL + Call WriteDataChannel + + Xor BX, BX + Mov AX, CCCA + Call WriteDataChannel + + Mov AX, CPF + Call WriteDataChannel + + Ret + +EndP StopAWENote + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetAWERegisters ; DS:SI = channel info table + ; CX = number of channels... + + Push CX + Push SI + + ; Stage 1. + ; Turn off any channel which has + ; a new note to play + ; If no new note to play and channel + ; is on, then get current position + + Xor DX, DX ; DX = oscillator number + +GetAWERegisters1: + Mov BX, [SI] + Test BH, 2 ; Note cut command + JZ GetAWERegisters2 + + Mov BX, 200h + Mov [SI], BX + + Call StopAWENote + Jmp GetAWERegisters4 + +GetAWERegisters2: + Test BL, 1 ; Channel on? + JZ GetAWERegisters4 + + Test BH, 1 ; New note? + JZ GetAWERegisters3 + + ; Fade out volume + Mov AX, DCYSUSV + Mov BX, 807Fh + Call WriteDataChannel + +; Call StopAWENote + + Jmp GetAWERegisters4 + +GetAWERegisters3: ; Get offset + Mov AX, CCCA + Call ReadDataChannel + + Xor BX, BX + And EAX, 00000000111111111111111111111111b + Inc EAX ; Interpolator correction + ; EAX = address in sound memory + Mov BL, [SI+36h] ; BL = sample number + LEA BX, [EBX*4+EBX] + ShL BX, 2 + Add BX, Offset AWEDataTable + + Cmp Byte Ptr [SI+0Ah], 8 + JB GetAddressNoLoop + JE GetAddressForwardsLoop + +GetAddressPingPongLoop: + Cmp EAX, [CS:BX+16] + JB SetOldAddress + + Neg EAX + Add EAX, [CS:BX+8] + Jmp SetOldAddress1 + +GetAddressNoLoop: + Cmp EAX, [CS:BX+4] ; Start loop + JB SetOldAddress + + Call StopAWENote + + ; OK.. gotta turn off channel + Mov Word Ptr [SI], 0 + Test Byte Ptr [SI+3Ah], 80h + JNZ GetAWERegisters4 + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Signify channel off + + Jmp GetAWERegisters4 + +GetAddressForwardsLoop: +SetOldAddress: + Sub EAX, [CS:BX] ; EAX = address in sample + JNS SetOldAddress1 + + Xor EAX, EAX + +SetOldAddress1: + Push CX + Mov CL, Compress + ShL EAX, CL + Pop CX + + XChg [SI+4Ch], EAX + Mov [SI+2Ch], EAX + +GetAWERegisters4: + Add SI, 128 + + Inc DX + Dec CX + JNZ GetAWERegisters1 + + Pop SI + Pop CX + + Xor DX, DX ; DX = oscillator number + +SetAWERegisters1: + ; Stage 2. + ; If new frequency, play new frequency + ; If new volume, play new volume + ; If new pan, play new pan + ; If new note, set ENVVOL, ENVVAL, SUSDCY, ATKHLDV, LFO1VAL, HLDATK + ; LFO2VAL, IP, IFATN, PEFE, FMMOD, TREMFRQ, FM2FRQ2 + ; PSST, CSL, CCCA + ; VTFT, CVCF, DCYSUSV, PTRX, CPF + + Push CX + Mov CX, [SI] + Test CL, 1 ; Channel on? + JZ SetAWERegistersEnd + + Test CH, 1 ; New note? + JZ SetAWERegisters2 + + Xor BX, BX + Mov BL, [SI+36h] + LEA DI, [EBX*4+EBX] + ShL DI, 2 + Add DI, Offset AWEDataTable + + Mov AX, DCYSUSV + Mov BX, 80h + Call WriteDataChannel + + Mov AX, VTFT + Xor EBX, EBX + Call WriteDataChannel + + Mov AX, CVCF + Call WriteDataChannel + + Cmp DWord Ptr [CS:DI], 0FFFFFFFFh + JE SetAWERegistersError + + Mov AX, PTRX + Call WriteDataChannel + + Mov AX, CPF + Call WriteDataChannel + + + Mov AX, ENVVOL + Mov BX, 8000h + Call WriteDataChannel + + Mov AX, ENVVAL + Mov BX, 8000h + Call WriteDataChannel + + Mov AX, SUSDCY + Mov BX, 7F7Fh + Call WriteDataChannel + + Mov AX, ATKHLDV + Call WriteDataChannel + + Mov AX, LFO1VAL + Mov BX, 8000h + Call WriteDataChannel + + Mov AX, HLDATK + Mov BX, 7F7Fh + Call WriteDataChannel + + Mov AX, LFO2VAL + Mov BX, 8000h + Call WriteDataChannel + + Call SetAWEFrequency + Call SetAWEVolume + + Mov AX, PEFE + Xor BX, BX + Call WriteDataChannel + + Mov AX, FMMOD + Call WriteDataChannel + + Mov AX, TREMFRQ + Mov BX, 10h + Call WriteDataChannel + + Mov AX, FM2FRQ2 + Call WriteDataChannel + + + Mov EBX, [CS:DI+4] + Dec EBX ; Interpolator offset + Mov AX, PSST + Call WriteDataChannel + + Call SetAWEPan + + Mov AL, [CS:VolumeTable+6] ; Chorus + ShL EAX, 24 + Mov EBX, [CS:DI+8] + Dec EBX ; Interpolator offset + Or EBX, EAX + Mov AX, CSL + Call WriteDataChannel + + Mov AL, [SI+3Fh] + ShL EAX, 28 + + Push CX + Mov CL, Compress + Mov EBX, [SI+4Ch] + ShR EBX, CL + Pop CX + Add EBX, [CS:DI] + Dec EBX ; Interpolator offset + Or EBX, EAX + + Mov AX, CCCA ; Current address. + Call WriteDataChannel + + + Mov AX, VTFT + Mov EBX, 0FFFFh + Call WriteDataChannel + + Mov AX, CVCF + Call WriteDataChannel + + Mov AX, DCYSUSV + Mov BX, 7F7Fh + Call WriteDataChannel + + Mov AX, PTRX + Mov EBX, 40000000h ; 25% reverb + Or BH, [CS:VolumeTable+7] + Call WriteDataChannel + + Mov AX, CPF + Call WriteDataChannel + Jmp SetAWERegistersEnd + +SetAWERegisters2: + Test CL, 32 ; Frequency change? + JZ SetAWERegisters3 + + Call SetAWEFrequency + +SetAWERegisters3: + Test CL, 64 ; Volume change? + JZ SetAWERegisters4 + + Call SetAWEVolume + +SetAWERegisters4: + Test CH, 80h ; New pan? + JZ SetAWERegistersEnd + + Call SetAWEPan + +SetAWERegistersEnd: + Pop CX + And Word Ptr [SI], 0111100010011111b + + Add SI, 128 + + Inc DX + Dec CX + JNZ SetAWERegisters1 + + Ret + +SetAWERegistersError: + Call StopAWENote + + Mov Word Ptr [SI], 0 + Test Byte Ptr [SI+3Ah], 80h + JNZ SetAWERegistersEnd + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Signify channel off + + Jmp SetAWERegistersEnd + +EndP SetAWERegisters + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ACKIRQ + + Mov AL, 20h + Cmp CS:IRQ, 7 + JBE ACKIRQ1 + + Out 0A0h, AL + +ACKIRQ1: + Out 20h, AL + Ret + +EndP ACKIRQ + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc CheckMIDI + + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Xor BX, BX + Mov DX, MIDIPort + + Mov BL, [MIDIBufferTail] + Test DX, DX + JZ CheckMIDIEnd + + Inc DX + +CheckMIDIAgain: + In AL, DX + + Test AL, AL + JS CheckMIDIAgain + + Dec DX + In AL, DX + + Cmp AL, 0F0h + JAE CheckMIDIEnd + + Inc BL + Cmp BL, MIDIBufferHead + JE CheckMIDIEnd + + Mov [MIDIBuffer+BX], AL + Mov [MIDIBufferTail], BL + +CheckMIDIEnd: + Pop DS + Ret + +EndP CheckMIDI + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc MIDIIRQHandler + + Push AX BX DX + + Mov DX, CS:MixerPort + Mov AL, 82h + Out DX, AL + Inc DL + In AL, DX + + Test AL, 4 + JZ MIDIIRQHandlerEnd + + Call CheckMIDI + +MIDIIRQHandlerEnd: + Call AckIRQ + + Pop DX BX AX + IRet + + +EndP MIDIIRQHandler + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SBIRQHandler + + PushAD + Push DS + Push ES + + StI + + Push CS + Pop DS + Assume DS:Driver + +SBIRQHandlerAgain: + Mov DX, MixerPort + Mov AL, 82h + Out DX, AL + Inc DL + In AL, DX + + Test AL, 4 + JZ NoMIDIIRQ + + Push AX + Call CheckMIDI + Pop AX + +NoMIDIIRQ: +; Test AL, 2 +; JZ No16BitIRQ +; +; Push AX +; Mov DX, MixerPort +; Add DL, 0Fh-4 +; In AL, DX +; Pop AX +; +; No16BitIRQ: + Test AL, 1 + JNZ SB8BitIRQ + +SBNo8BitIRQ: + Call AckIRQ + Jmp SBEndIRQ + +SB8BitIRQ: + Mov DX, MixerPort + Add DL, 0Eh-4 + In AL, DX ; 8-bit IRQ ack. + + Add DL, 0Ch-0Eh + + Mov AL, 80h ; Output block of silence + Call SBOut + Mov AX, BlockLength2 + Call SBOut + Mov AL, AH + Call SBOut + + Mov AL, 0D3h + Call SBOut + + ClD + Call ACKIRQ + + Inc IRQFlag + JNZ SBEndIRQ + + Call SaveEMSPageFrame + Assume DS:Nothing + +SB8BitIRQAgain: + Call Update ; Returns DS:SI, CX + + Mov BX, BlockLength + Cmp BX, BlockLength2 + JE SBIRQHandler2 + Mov BlockLength2, BX + + Mov DX, SB16BasePort + Add DL, 0Ch + + Mov AL, 0D0h + Call SBOut + + Mov AL, 80h ; Output block of silence + Call SBOut + Mov AL, BL + Call SBOut + Mov AL, BH + Call SBOut + +SBIRQHandler2: + Call SetAWERegisters + Sub CS:IRQFlag, 1 + JNC SB8BitIRQAgain + + Call RestoreEMSPageFrame + +SBEndIRQ: + Pop ES + Pop DS + PopAD + + IRet + +EndP SBIRQHandler + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc AWEIRQHandler ; IRQ Handler has to + ; 1) Update AWE registers + ; 2) Update song position + Push AX + Push DS + + Mov AX, AWEUpdateTimer + Add AWEUpdateCount, AX + JC AWEIRQHandler1 + + Mov AL, 20h + Out 20h, AL + Jmp AWEIRQHandler2 + +AWEIRQHandler1: + PushF + Call [OldIRQHandler] + +AWEIRQHandler2: + Xor AWEUpdateFlag, 1 + JZ AWEIRQHandlerEnd + + PushAD + Push ES + + ClD + + Call SaveEMSPageFrame + Call Update ; Returns DS:SI, CX + Call SetAWERegisters + Call RestoreEMSPageFrame + + Pop ES + PopAD + +AWEIRQHandlerEnd: + Pop DS + Pop AX + IRet + +EndP AWEIRQHandler + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc EnableRAM + + Mov DX, BasePort + Mov CX, 29 + +EnableRAM1: + Mov AX, DCYSUSV + Or AX, CX + Mov BX, 80h + Call WriteData + + Mov AX, VTFT + Or AX, CX + Xor EBX, EBX + Call WriteData + + Mov AX, CVCF + Or AX, CX + Xor EBX, EBX + Call WriteData + + Mov AX, PTRX + Or AX, CX + Mov EBX, 40000000h + Call WriteData + + Mov AX, CPF + Or AX, CX + Mov EBX, 40000000h + Call WriteData + + Mov AX, PSST + Or AX, CX + Xor EBX, EBX + Call WriteData + + Mov AX, CSL + Or AX, CX + Xor EBX, EBX + Call WriteData + + Mov AX, CCCA + Or AX, CX + Mov EBX, 6000000h ; Left write + Call WriteData + + Dec CX + JNS EnableRAM1 + + Ret + +EndP EnableRAM + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc TestAWE ; Given DX = baseport. + + Push DX + + Add DX, 802h + In AL, DX + In AL, DX + Not AL + Mov BL, AL + Out DX, AL + In AL, DX + Cmp AL, BL + JNE TestAWE1 ; Register changed + + In AX, DX ; Is upper part of pointer + Mov BX, AX ; changing? + Mov CX, 128 + +TestAWE2: + In AX, DX + Cmp AL, BL + JNE TestAWE1 + Cmp AH, BH + JNE TestAWE3 + + Dec CX + JNZ TestAWE2 + Jmp TestAWE1 + +TestAWE3: + Pop DX + + ClC + Ret + +TestAWE1: + Pop DX + StC + Ret + +EndP TestAWE + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSetAWE + + Mov CX, 31 + +InitSetAWE1: + Mov AX, 31 + Sub AX, CX + Mov BX, [SI] + Or AX, INIT1 + Call WriteData + + Add SI, 2 + + Dec CX + JNS InitSetAWE1 + + Mov CX, 31 + +InitSetAWE2: + Mov AX, 31 + Sub AX, CX + Mov BX, [SI] + Or AX, INIT2 + Call WriteData + + Add SI, 2 + + Dec CX + JNS InitSetAWE2 + + Mov CX, 31 + +InitSetAWE3: + Mov AX, 31 + Sub AX, CX + Mov BX, [SI] + Or AX, INIT3 + Call WriteData + + Add SI, 2 + + Dec CX + JNS InitSetAWE3 + + Mov CX, 31 + +InitSetAWE4: + Mov AX, 31 + Sub AX, CX + Mov BX, [SI] + Or AX, INIT4 + Call WriteData + + Add SI, 2 + + Dec CX + JNS InitSetAWE4 + + Ret + +EndP InitSetAWE + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitAWE + + Push CS + Pop DS + Assume DS:Driver + + Mov DX, BasePort + + Mov AX, HWCF1 + Mov BX, 59h + Call WriteData + + Mov AX, CFG2 + Mov BX, 20h + Call WriteData + + Mov CX, 31 + +InitAwe1: + Mov BX, 80h + Mov AX, DCYSUSV + Or AX, CX + Call WriteData + + Xor EBX, EBX + Mov AX, ENVVOL + Or AX, CX + Call WriteData + + Mov AX, ENVVAL + Or AX, CX + Call WriteData + + Mov AX, SUSDCY + Or AX, CX + Call WriteData + + Mov AX, ATKHLDV + Or AX, CX + Call WriteData + + Mov AX, LFO1VAL + Or AX, CX + Call WriteData + + Mov AX, HLDATK + Or AX, CX + Call WriteData + + Mov AX, LFO2VAL + Or AX, CX + Call WriteData + + Mov AX, IP + Or AX, CX + Call WriteData + + Mov AX, IFATN + Or AX, CX + Call WriteData + + Mov AX, PEFE + Or AX, CX + Call WriteData + + Mov AX, FMMOD + Or AX, CX + Call WriteData + + Mov AX, TREMFRQ + Or AX, CX + Call WriteData + + Mov AX, FM2FRQ2 + Or AX, CX + Call WriteData + + Mov AX, PTRX + Or AX, CX + Call WriteData + + Mov AX, VTFT + Or AX, CX + Call WriteData + + Mov AX, PSST + Or AX, CX + Call WriteData + + Mov AX, CSL + Or AX, CX + Call WriteData + + Mov AX, CCCA + Or AX, CX + Call WriteData + + Dec CX + JNS InitAWE1 + + Mov CX, 31 + +InitAWE8: + Mov AX, CPF + Or AX, CX + Call WriteData + + Mov AX, CVCF + Or AX, CX + Call WriteData + + Dec CX + JNS InitAWE8 + ; Initialise still... + Mov AX, SMALR + Call WriteData + + Mov AX, SMARR + Call WriteData + + Mov AX, SMALW + Call WriteData + + Mov AX, SMARW + Call WriteData + + Mov SI, Offset InitTable1 + Call InitSetAWE + + ; Wait for 1024 sample periods + Mov AX, WC + Call ReadData + + Mov BX, AX + Mov CX, AX + Add CX, 400h ; 1024 + Cmp BX, CX + JB InitAWE3 + +InitAWE4: + Mov AX, WC + Call ReadData + Cmp AX, CX + JA InitAWE4 + +InitAWE3: + Mov AX, WC + Call ReadData + Cmp AX, CX + JB InitAWE3 + + Mov SI, Offset InitTable2 + Call InitSetAWE + + Mov SI, Offset InitTable3 + Call InitSetAWE + + Mov AX, HWCF4 + Xor EBX, EBX + Call WriteData + + Mov AX, HWCF5 + Mov EBX, 83h + Call WriteData + + Mov AX, HWCF6 + Mov EBX, 8000h + Call WriteData + + Mov SI, Offset InitTable4 + Call InitSetAWE + + Mov AX, HWCF3 + Mov BX, 4 + Call WriteData + + Ret + +EndP InitAWE + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitDRAMRefresh + + Mov AX, DCYSUSV+1Eh + Mov BX, 80h + Call WriteData + + Mov AX, DCYSUSV+1Fh + Call WriteData + +; + + Mov AX, VTFT+1Eh + Xor EBX, EBX + Call WriteData + + Mov AX, CVCF+1Eh + Call WriteData + + Mov AX, VTFT+1Fh + Call WriteData + + Mov AX, CVCF+1Fh + Call WriteData + +; + + Mov AX, PTRX+1Eh + Call WriteData + + Mov AX, CPF+1Eh + Call WriteData + + Mov AX, PTRX+1Fh + Call WriteData + + Mov AX, CPF+1Fh + Call WriteData + +; + + Mov AX, PSST+1Eh + Call WriteData + Mov AX, PSST+1Fh + Call WriteData + + Mov BX, 0FFFFh + Mov AX, CSL+1Eh + Call WriteData + Mov AX, CSL+1Fh + Call WriteData + + Xor BX, BX + Mov AX, CCCA+1Eh + Call WriteData + Mov AX, CCCA+1Fh + Call WriteData + + Ret + +EndP InitDRAMRefresh + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetDSP Far ; AX = Port + + Push AX + Push CX + Push DX + + Mov DX, AX + Add DL, 6 + Mov AL, 1 + Out DX, AL + + In AL, DX + In AL, DX + In AL, DX + In AL, DX + + Xor AL, AL + Out DX, AL + + Add DL, 8 + Mov CX, 200 + +ResetDSP1: + In AL, DX + Test AL, AL + JS ResetDSP2 + Loop ResetDSP1 + Jmp ResetDSP3 + +ResetDSP2: + Sub DL, 4 + In AL, DX + Cmp AL, 0AAh + JE ResetDSP4 + Add DL, 4 + Loop ResetDSP1 + +ResetDSP3: + StC + +ResetDSP4: + Pop DX + Pop CX + Pop AX + Ret + +EndP ResetDSP + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SBGetRegister + + Out DX, AL + Inc DX + In AL, DX + Dec DX + + Ret + +EndP SBGetRegister + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SBIn ; DX = 2xEh, returns AL + +SBIn1: + In AL, DX + + ShR AL, 7 + LoopZ SBIn + +; Test AL, AL +; JNS SBIn1 + + Add DL, 0Ah-0Eh ; DX = 2xAh -> Data read port + In AL, DX + Add DL, 0Eh-0Ah + + Ret + +EndP SBIn + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far + + Push CS + Pop DS + Assume DS:Driver + + Mov Forced, AL + + Mov DX, BasePort + Cmp DX, 0FFFFh + JE DetectCard1 + + Cmp DX, 620h + JB DetectCard3 + Cmp DX, 680h + JA DetectCard3 + + Call TestAWE + JNC DetectCardFound + Ret + +DetectCard1: + Mov DX, 620h + +DetectCard2: + Call TestAWE + JNC DetectCardFound + + Add DL, 20h + Cmp DL, 80h + JBE DetectCard2 + +DetectCard3: + StC + Ret + +DetectCardFound: + Mov BasePort, DX + + ; Initialise AWE 32 + Call InitAWE + Call InitDRAMRefresh + + ; Detect amount of RAM. + + Mov DX, BasePort + Mov CX, 29 + +DetectCardMemory1: + Mov AX, DCYSUSV + Or AX, CX + Mov BX, 80h + Call WriteData + + Mov AX, VTFT + Or AX, CX + Xor EBX, EBX + Call WriteData + + Mov AX, CVCF + Or AX, CX + Xor EBX, EBX + Call WriteData + + Mov AX, PTRX + Or AX, CX + Mov EBX, 40000000h + Call WriteData + + Mov AX, CPF + Or AX, CX + Mov EBX, 40000000h + Call WriteData + + Mov AX, PSST + Or AX, CX + Xor EBX, EBX + Call WriteData + + Mov AX, CSL + Or AX, CX + Xor EBX, EBX + Call WriteData + + Mov AX, CCCA + Or AX, CX + Mov EBX, 4000000h ; Left read + + Test CL, 2 + JZ DetectCardMemory2 + + Mov EBX, 6000000h ; Left write + +DetectCardMemory2: + Call WriteData + + Dec CX + JNS DetectCardMemory1 + + Xor EDI, EDI ; Amount of memory stored in + ; EDI + + Mov AX, SMALW + Mov EBX, 200000h + Call WriteData + + Mov AX, SMLD + Mov BX, 0FFFFh + Call WriteData + + Mov AX, SMLD + Mov BX, 5555h + Call WriteData + + Mov AX, SMLD + Mov BX, 0AAAAh + Call WriteData + + Mov AX, SMALR + Mov EBX, 200000h + Call WriteData + + Mov AX, SMLD + Call ReadData + + Mov AX, SMLD + Call ReadData + Cmp AX, 0FFFFh + JNE DetectCardMemory6 + + Mov AX, SMLD + Call ReadData + Cmp AX, 5555h + JNE DetectCardMemory6 + + Mov AX, SMLD + Call ReadData + Cmp AX, 0AAAAh + JNE DetectCardMemory6 + + Mov EDI, 20000h + +DetectCardMemory3: ; Set read/write addresses.. + Mov AX, SMALW + Mov EBX, EDI + Add EBX, 200000h + Call WriteData + + Mov AX, SMLD + Mov BX, 5555h + Call WriteData + + Mov AX, SMLD + Mov BX, 0AAAAh + Call WriteData + + Mov AX, SMALR + Mov EBX, 200000h + Call WriteData + + Mov AX, SMLD + Call ReadData + + Mov AX, SMLD + Call ReadData + Cmp AX, 0FFFFh + JNE DetectCardMemory5 + + Mov AX, SMALR + Mov EBX, EDI + Add EBX, 200000h + Call WriteData + + Mov AX, SMLD + Call ReadData + + Mov AX, SMLD + Call ReadData + Cmp AX, 5555h + JNE DetectCardMemory5 + + Mov AX, SMLD + Call ReadData + Cmp AX, 0AAAAh + JNE DetectCardMemory5 + +DetectCardMemory4: + Add EDI, 20000h + Cmp EDI, 0E00000h + JB DetectCardMemory3 + +DetectCardMemory5: + Cmp EDI, 0DFFFE0h + JB DetectCardMemory7 + + Mov EDI, 0DFFFE0h + +DetectCardMemory7: + Test EDI, EDI + JZ DetectCardMemory6 + + Mov AWEMemory, EDI + + Mov MixerPort, 210h + Mov AX, BasePort + Sub AX, 400h + Call ResetDSP + JNC DetectMixer2 + +DetectMixer1: + Mov AX, MixerPort + Call ResetDSP + JNC DetectMixer2 + +DetectMixer3: + Add MixerPort, 10h + Cmp MixerPort, 280h + JBE DetectMixer1 + + Mov DX, BasePort + Sub DX, 400h + Mov MixerPort, DX + + Jmp DetectCard4 + +DetectMixer2: ; OK... DSP found. + ; Get DSP version + Mov DX, AX + Add DL, 0Ch ; 2xCh -> Data ready to send... + + Mov CX, 200 + +DetectMixerLoop1: + In AL, DX +; Test AL, AL +; JS DetectMixerLoop1 + ShR AL, 7 + LoopNZ DetectMixerLoop1 + + Mov AL, 0E1h ; Get DSP version command + Out DX, AL + + Add DL, 0Eh-0Ch ; DX = 2xEh -> Data available status + + Call SBIn + Mov AH, AL ; AH = Major version number + Call SBIn ; AL = Minor version number + + Cmp AX, 40Ch ; SB DSP = 4.12+ + JB DetectMixer3 + + Sub DL, 0Eh + Mov MixerPort, DX + +DetectCard4: + Mov SB16BasePort, DX + Add MixerPort, 4 ; Mixerport + + Add DL, 4 + + Mov AL, 30h + Call SBGetRegister + ShR AL, 3 + Mov VolumeTable, AL + + Mov AL, 31h + Call SBGetRegister + ShR AL, 3 + Mov [VolumeTable+1], AL + + Mov AL, 44h + Call SBGetRegister + ShR AL, 4 + Mov [VolumeTable+2], AL + + Mov AL, 45h + Call SBGetRegister + ShR AL, 4 + Mov [VolumeTable+3], AL + + Mov AL, 46h + Call SBGetRegister + ShR AL, 4 + Mov [VolumeTable+4], AL + + Mov AL, 47h + Call SBGetRegister + ShR AL, 4 + Mov [VolumeTable+5], AL + + Mov DX, MixerPort + Mov AX, 0C034h + Out DX, AX + + Mov AL, 35h + Out DX, AX + + Mov DX, MixerPort + Mov AL, 80h ; IRQ select + Out DX, AL + Inc DL ; 2x5h = Mixer data port + + In AL, DX + + Dec DL + + Mov BX, IRQ + Cmp BX, 0FFFFh + JE DetectCardIRQ1 + Cmp Forced, 0 + JE DetectCardIRQ1 + + Mov AH, 11h + Cmp BL, 2 + JE SetCardIRQ1 + Cmp BL, 9 + JE SetCardIRQ1 + + Mov AH, 12h + Cmp BL, 5 + JE SetCardIRQ1 + + Mov AH, 14h + Cmp BL, 7 + JE SetCardIRQ1 + + Mov AH, 18h + Cmp BL, 10 + JE SetCardIRQ1 + + Jmp NoWindows + +SetCardIRQ1: + Mov AL, 80h + Out DX, AL + Inc DL + Mov AL, AH + Out DX, AL + Dec DL + Jmp DetectCard6 + +DetectCardIRQ1: + Mov BX, 2 + Test AL, 1 + JNZ DetectCardIRQ2 + + Mov BL, 5 + Test AL, 2 + JNZ DetectCardIRQ2 + + Mov BL, 7 + Test AL, 4 + JNZ DetectCardIRQ2 + + Mov BL, 10 + Test AL, 8 + JNZ DetectCardIRQ2 + + StC + Ret + +DetectCardIRQ2: + Cmp IRQ, 0FFFFh + JE DetectCardIRQ3 + + Cmp BX, IRQ + JE DetectCard6 + + StC + Ret + +DetectCardIRQ3: + Mov IRQ, BX + +DetectCard6: + Mov AX, 1600h ; Windows detection. + Int 2Fh + Test AL, 7Fh + JZ NoWindows + + Mov SBIRQMode, 1 + +NoWindows: + Mov EAX, 'Jeff' + ClC + Ret + +DetectCardMemory6: + StC + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetSamplingRate + + PushA + + Mov AX, CS:SB16BasePort + Mov DX, AX + Call ResetDSP + Add DL, 0Ch + ; Set mixing frequency + Mov AL, 40h + Call SBOut + Mov AL, 211 + Call SBOut ; 22222 Hz. + + Mov AL, 80h + Call SBOut + Mov AX, BlockLength + Dec AX + Call SBOut + Mov AL, AH + Call SBOut + + PopA + Ret + +EndP SetSamplingRate + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMIDIIRQ + + PushAD + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Add DI, Offset IRQData + Mov BX, [DI] + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset MIDIIRQHandler + + XChg [ES:BX], EAX + Mov OldIRQHandler, EAX + + Mov AX, IMR + And AX, [DI+2] + + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Pop ES + Pop DS + PopAD + + Ret + +EndP SetMIDIIRQ + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + + PushAD + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Add DI, Offset IRQData + Mov BX, [DI] + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset SBIRQHandler + + XChg [ES:BX], EAX + Mov OldIRQHandler, EAX + + Mov AX, IMR + And AX, [DI+2] + + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Pop ES + Pop DS + PopAD + + Ret + +EndP SetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIRQ + + PushAD + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Mov BX, [IRQData+DI] + + Mov EAX, OldIRQHandler + Mov [ES:BX], EAX + + Mov AX, IMR + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Pop ES + Pop DS + PopAD + + Ret + +EndP ResetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitMIDI + + Mov DX, 330h + Call DetectUART + JC DetectMIDI1 + + Mov MIDIPort, 330h + Jmp DetectMIDIEnd + +DetectMIDI1: + Mov DX, 300h + Call DetectUART + JC DetectMIDIEnd + + Mov MIDIPort, 300h + +DetectMIDIEnd: + Ret + +EndP InitMIDI + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + Mov AX, CS + Mov DriverSegment1, AX + Mov DriverSegment2, AX + Mov DriverSegment3, AX + Mov DriverSegment4, AX + Mov DriverSegment5, AX + Mov DriverSegment6, AX + Mov DriverSegment7, AX + Mov DriverSegment8, AX + + In AL, 0A1h + Mov AH, AL + In AL, 21h + Mov IMR, AX + + Cmp SBIRQMode, 0 + JE InitSound1 + + Call SetIRQ + Call GetTempo + Call SetTempo + Call ResetMemory + Call SetSamplingRate + + Call InitMIDI + + Mov SI, Offset AWE32Msg2 + Mov AX, BasePort + + Mov BX, IRQ + + Mov ECX, AWEMemory + SHR ECX, 9 + + Ret + +InitSound1: + Call SetMIDIIRQ + Call GetTempo + Call SetTempo + Call ResetMemory + + Xor AX, AX + Mov ES, AX ; ES = 0 + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset AWEIRQHandler + + ClI + + XChg DWord Ptr [ES:20h], EAX ; Clock tick + Mov OldIRQHandler, EAX + + StI + +InitSound2: + Call InitMIDI + + Mov SI, Offset AWE32Msg + Mov AX, BasePort + + Mov EBX, AWEMemory + SHR EBX, 9 + + Ret + +EndP InitSound + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov SI, Offset AWE32ReinitMsg + Mov BX, 40 + Call SetInfoLine + + Call ResetUART + Call InitAWE + Call InitDRAMRefresh + + Cmp SBIRQMode, 0 + JE ReInitSound1 + + Call ResetIRQ + Call SetIRQ + Call SetSamplingRate + Call ReinitUART + Ret + +ReInitSound1: + Xor AX, AX + Mov ES, AX ; ES = 0 + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset AWEIRQHandler + + Mov DWord Ptr [ES:20h], EAX ; Clock tick + + Call ResetIRQ + Call SetMIDIIRQ + Call ReinitUART + + Ret + +EndP ReInitSound + Assume DS:Nothing + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + + Call GotoHomeDirectory + + ; Now to save config into driver file. + Push CS + Pop DS + Assume DS:Driver + + Mov AX, 3D02h ; Read write access + Mov DX, Offset DriverName + Int 21h + JC SaveConfig2 + + Mov BX, AX + + Mov AX, 4200h + Xor CX, CX + Mov DX, Offset CONFIGURATIONOFFSET + Int 21h + JC SaveConfig1 + + Mov AH, 40h + Mov CX, CONFIGSIZE + Mov DX, Offset Chorus + Int 21h + +SaveConfig1: + PushF + Mov AH, 3Eh + Int 21h + PopF + +SaveConfig2: + Call ResetIRQ + + Cmp SBIRQMode, 0 + JE UnInitSound1 + + Mov DX, SB16BasePort + Add DL, 0Ch + + Mov AL, 0D0h + Call SBOut + + Call ResetUART + +; Mov AX, SB16BasePort +; Call ResetDSP + + Call InitAWE + Ret + +UnInitSound1: + Mov AL, 34h + Out 43h, AL + + Xor AX, AX + Out 40h, AL + Out 40h, AL + + Mov ES, AX + Mov EAX, OldIRQHandler + Mov [ES:20h], EAX + + Mov AX, SB16BasePort + Call ResetDSP + Call ResetUART + Call InitAWE + Call ResetIRQ + Ret + +EndP UnInitSound + Assume DS:Nothing + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + Push CS + Pop DS + Assume DS:Driver + +Poll1: + Call [UARTBufferEmpty] + JNC PollEnd + + Xor BX, BX + + ClI + + Mov BL, MIDIBufferHead + Cmp BL, MIDIBufferTail + JZ PollEnd ; Nothing in queue + + Inc BL + Mov AL, [MIDIBuffer+BX] + Mov MIDIBufferHead, BL + + Call [UARTSend] + Jmp Poll1 + +PollEnd: + StI + Ret + +EndP Poll + Assume DS:Nothing + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Push AX + Push BX + Push DX + + Cmp CS:SBIRQMode, 0 + JE SetTempo1 + ; BlockLength = 55555/BPM + + Mov AX, 55555 + Xor DX, DX + Div BX + Dec AX + Mov BlockLength, AX + +; Mov DX, SB16BasePort +; Add DL, 0Ch + + Jmp SetTempo2 + +SetTempo1: + ; Frames per second = 2 * (0.4*Tempo) + Mov AX, 0C214h + Mov DX, 16h ; Ticks = (1193181/(2*0.4))/Tempo + Div BX + + ; AX contains counter. + Mov AWEUpdateTimer, AX + + Out 40h, AL ; Timer IRQ. + Mov AL, AH + Out 40h, AL + +SetTempo2: + Pop DX + Pop BX + Pop AX + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + Ret + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Mov CS:Stereo, AL + + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc LoadSample Far + ; if no sample, then do nothing + ; MemoryUsed = length of sample + ; if sustain loop, then use sustain + ; loop information + ; if no sustain loop, then use loop + ; information + ; if no loop or sustain loop, + ; memoryused += 16; (16 zero samples + ; at the end) + ; + PushAD + Push DS + Push ES + Push FS + + Push AX + + ClI + + Call EnableRAM ; Enable access to DRAM. + + ; Set destination address + Mov AX, SMALW + Mov EBX, CS:AWEMemoryUsed + Add EBX, 200000h + Call WriteData + + Mov DX, CS:BasePort + Add DX, 802h ; Index + Mov AX, 32+26 + Out DX, AX + + Pop AX + + Mov FS, CS:SongDataArea + LEA DI, [EAX*4+EAX] + ShL DI, 2 + Add DI, Offset AWEDataTable-20 + + Mov ECX, -1 + + Mov DWord Ptr [CS:DI], ECX ; Start + Mov DWord Ptr [CS:DI+4], ECX ; Loop start + Mov DWord Ptr [CS:DI+8], ECX ; Loop end + Mov DWord Ptr [CS:DI+12], ECX ; Size occupied + Mov DWord Ptr [CS:DI+16], ECX ; Size occupied + + Mov BP, AX + Add BP, BP + Mov BP, [FS:64910+BP] + + Xor CX, CX ; From the start of the sample.. + Call GetSampleLocation ; Returns DS:ESI, ECX = length + JC LoadSampleNoError + + JZ LoadSample1 + + ; 16 bit + + Mov CS:LoadSampleFuncF, Offset Load16BitSamplesForwards + Mov CS:LoadSampleFuncB, Offset Load16BitSamplesBackwards + + Jmp LoadSample2 + +LoadSample1: ; 8 bit + Mov CS:LoadSampleFuncF, Offset Load8BitSamplesForwards + Mov CS:LoadSampleFuncB, Offset Load8BitSamplesBackwards + +LoadSample2: + Mov AL, [FS:BP+12h] + Test AL, 30h ; Loop or sustain loop? + JZ LoadSampleNoLoop + + Mov EBX, [FS:BP+34h] ; Loop begin + Mov EDX, [FS:BP+38h] ; Loop end + Test AL, 20h ; Sustain loop? + JZ LoadSample3 + + ShR AL, 1 + Mov EBX, [FS:BP+40h] + Mov EDX, [FS:BP+44h] + Jmp LoadSample3 + +LoadSampleError: + ClC + Jmp LoadSampleEnd + +LoadSampleNoError: + StC + +LoadSampleEnd: + StI + Pop FS + Pop ES + Pop DS + PopAD + + Ret + +LoadSampleNoLoop: ; ECX contains length of sample + Mov EAX, ECX + Mov EDX, AWEMemoryUsed + Mov EBX, AWEMemory + Sub EBX, EDX ; EBX = AWEMemory remaining + + Mov CL, Compress + ShR EAX, CL ; Compress sample + Add EAX, 16 ; zeroes at end of sample + + Cmp EAX, EBX + JA LoadSampleError + + Mov ECX, EAX + Add AWEMemoryUsed, EAX ; Record memory as used + Mov [CS:DI+12], EAX + + Add EDX, 200000h + + Sub ECX, 16 ; Number of samples to transfer + Mov [CS:DI], EDX + Add EDX, ECX + Mov [CS:DI+4], EDX ; Loop start + Add EDX, 14 + Mov [CS:DI+8], EDX ; Loop end + + ; Now to transfer samples to AWE32 + Call [CS:LoadSampleFuncF] + ; Now to shove a whole lot of zeroes + Xor AX, AX + Mov CX, 16 + +LoadSampleNoLoop2: + Out DX, AX + Loop LoadsampleNoLoop2 + + Jmp LoadSampleNoError + +LoadSample3: ; OK... EBX = loop start + ; EDX = loop end + ; AL&40h = ping pong + Test AL, 40h + JNZ LoadSamplePingPong + + Mov CL, Compress + + Push EBX + + ShR EDX, CL + ShR EBX, CL + Mov EAX, EDX + Add EAX, 2 ; For loop fixing + + Mov ECX, AWEMemory + Sub ECX, AWEMemoryUsed ; ECX = AWEMemoryRemaining + + Cmp EAX, ECX + Pop ECX + JA LoadSampleError ; Sufficient memory? + Push ECX + + Mov ECX, EAX + Mov EAX, AWEMemoryUsed + Add AWEMemoryUsed, ECX + Mov [CS:DI+12], ECX + + Sub ECX, 2 + + Add EAX, 200000h + Mov [CS:DI], EAX + + Add EDX, EAX + Add EAX, EBX + + Mov [CS:DI+4], EAX + Mov [CS:DI+8], EDX + + Call [CS:LoadSampleFuncF] + ; Now to fix loop.. 1 extra + ; sample. + + Pop ESI ; Loop start + Test Byte Ptr [FS:BP+12h], 2 + JZ LoadSampleForwards1 + + Add ESI, ESI + +LoadSampleForwards1: + Int 3 + + Mov ECX, 2 + Call [CS:LoadSampleFuncF] + + Jmp LoadSampleNoError + +LoadSamplePingPong: + Mov CL, Compress + ShR EDX, CL + ShR EBX, CL + + Mov EAX, EDX + Add EAX, EDX + Sub EAX, EBX + Inc EAX + + Mov ECX, AWEMemory + Sub ECX, AWEMemoryUsed + + Cmp EAX, ECX + JA LoadSampleError + + Mov [CS:DI+12], EAX + Mov ECX, AWEMemoryUsed + Add AWEMemoryUsed, EAX + + Add ECX, 200000h + Add EAX, ECX + Dec EAX + + Mov [CS:DI], ECX + Add ECX, EBX + Mov [CS:DI+4], ECX + Mov [CS:DI+8], EAX + + Mov EAX, [CS:DI] + Add EAX, EDX + Mov [CS:DI+16], EAX + + Mov ECX, EDX + Sub EDX, EBX + Push EDX + + Call [CS:LoadSampleFuncF] + + Pop ECX + Inc ECX + + Call [CS:LoadSampleFuncB] + + Jmp LoadSampleNoError + +EndP LoadSample + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + PushAD + + LEA DI, [EAX*4+EAX] ; DI = AX * 5 + ShL DI, 2 + Add DI, Offset AWEDataTable + + Mov EBX, [CS:DI+12] + Mov EAX, CS:AWEMemoryUsed + Sub EAX, EBX + Add EAX, 200000h + Cmp EAX, [CS:DI] + JNE ReleaseSample1 + + Sub AWEMemoryUsed, EBX +ReleaseSample1: + Mov EAX, -1 + Mov [CS:DI], EAX + Mov [CS:DI+4], EAX + Mov [CS:DI+8], EAX + Mov [CS:DI+12], EAX + + PopAD + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Push CS + Pop ES + + Xor EAX, EAX + Mov CS:AWEMemoryUsed, EAX + + Mov DI, Offset AWEDataTable + Mov CX, 1000 + Mov AX, 0FFFFh + Rep StosW + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + Push CS + Pop DS + Assume DS:Driver + + Mov SI, Offset AWE32Status + + Mov EAX, AWEMemory + Sub EAX, AWEMemoryUsed + SHR EAX, 9 + + ClC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset GUSScreenList + + ClC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far ; Returns AX, given DI + + Xor AH, AH + Mov AL, [CS:VolumeTable+DI] + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far ; Given AX, DI + + Push DS + Push DX + + Push CS + Pop DS + Assume DS:Driver + + Mov [VolumeTable+DI], AL + + Mov DX, MixerPort + Mov AL, 30h + Mov AH, [VolumeTable] + ShL AH, 3 + Out DX, AX + + Mov AL, 31h + Mov AH, [VolumeTable+1] + ShL AH, 3 + Out DX, AX + + Mov AL, 44h + Mov AH, [VolumeTable+2] + ShL AH, 4 + Out DX, AX + + Mov AL, 45h + Mov AH, [VolumeTable+3] + ShL AH, 4 + Out DX, AX + + Mov AL, 46h + Mov AH, [VolumeTable+4] + ShL AH, 4 + Out DX, AX + + Mov AL, 47h + Mov AH, [VolumeTable+5] + ShL AH, 4 + Out DX, AX + + Pop DX + Pop DS + Ret + +EndP SetVariable + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UARTOut + + Ret + +EndP UARTOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + + +InterpretState DB 0 +InterpretType DB 0 + +Proc SendUARTOut Far ; Local interpreter activated with 0F0h 0F0h. + + Mov AH, CS:InterpretState + Cmp AH, 2 + JB SendUARTOut1 + +; In interpreter. + JE SendUARTOut3 + +; Have InterpretType, now get parameter, then return to normal. + + Push BX + + Mov BL, CS:InterpretType ; Want BX = InterpretType*64+Channel + ; + ShL BX, 6 + Add BL, [DI+20h] + And BX, 127 + Mov [CS:AWEParameters+BX], AL + + Pop BX + + Mov CS:InterpretState, 0 + + Test SI, SI + JZ SendUARTOut4 + + Or Byte Ptr [SI], 64 + +SendUARTOut4: + Ret + +SendUARTOut3: + Mov InterpretType, AL + Jmp SendUARTOutStateInc + +SendUARTOut1: + Cmp AL, 0F0h + JNE SendUARTOut2 + +SendUARTOutStateInc: + Inc CS:InterpretState + Ret + +SendUARTOut2: + Test AH, AH + JZ SendUARTOutEnd + + Push AX + Mov AL, 0F0h + Call UARTOut + Pop AX + Mov CS:InterpretState, 0 + +SendUARTOutEnd: + Cmp AL, 0FCh + JE ResetFilters + Cmp AL, 0FAh + JE ResetFilters + + Cmp AL, 0FFh + JNE SendUARTOutNoClear + +ResetFilters: + PushA + Push ES + + Push CS + Pop ES + + Mov DI, Offset AWEParameters + Mov CX, 32 + Or AX, -1 + Rep StosW + Mov CX, 32 + Inc AX + Rep StosW + + Pop ES + PopA + +SendUARTOutNoClear: + Call UARTOut + Ret + +EndP SendUARTOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 30 ; Maximum number of channels the + ; driver can handle. +StopAfterPlay DW 0 +DefaultChannels DW 30 +DriverFlags DW 1 ; MIDI Out supported + + DW 4 Dup (0) + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + + DW Offset SendUARTOut ; For MIDI Out + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/AWE32DRV.ASM b/SoundDrivers/AWE32DRV.ASM new file mode 100755 index 0000000..e101d68 --- /dev/null +++ b/SoundDrivers/AWE32DRV.ASM @@ -0,0 +1,3961 @@ + + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + + Comment ~ + +Index = BasePort + 802h + + 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ + ³ .............................. ³ Register ³ Channel Number ³ + ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + + + ~ + +OldIRQHandler DD 0 +AWEMemory DD 0 +AWEMemoryUsed DD 0 +AWEUpdateCount DW 0 + +AWEUpdateTimer DW 0 + +LoadSampleFuncF DW 0 +LoadSampleFuncB DW 0 + +AWEDataTable DD 5*100 Dup (0) ; Start, Startloop, Endloop, Size +MIDIPort DW 0 +MIDIBuffer DB 256 Dup (0) +MIDIBufferHead DB 0 +MIDIBufferTail DB 0 + +DMABuffer DW 0 + +SB16BasePort DW 0 +MixerPort DW 0 +Step DW 1 +AWEUpdateFlag DB 0 +Compress DB 0 + DB 0 + +SBIRQMode DB 0 +BlockLength DW 100 +BlockLength2 DW 100 + +AWE32Msg DB "Sound Blaster AWE 32 detected", 13 + DB "Address ", 0FDh, "Xh, ", 0FDh, "Dk Memory", 0 + +AWE32Msg2 DB "Sound Blaster AWE 32 detected", 13 + DB "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, DMA ", 0FDh, "D", 0 + +AWE32Status DB "FreeAWE ", 0FDh, "Dk", 0 + +AWE32ReinitMsg DB "Sound Blaster AWE 32 reinitialised", 0 +Stereo DB 0 +Forced DB 0 +DriverName DB "ITAWE32.DRV", 0 + +FrequencyError DB "AWE Hardware frequency limit exceeded -> Note terminated", 0 + +IRQFlag DB 0FFh + +IRQData Label Word + DW 20h, 1111111111111110b ; IRQ 0 + DW 24h, 1111111111111101b ; IRQ 1 + DW 28h, 1111110111111011b ; IRQ 2 + DW 2Ch, 1111111111110111b ; IRQ 3 + DW 30h, 1111111111101111b ; IRQ 4 + DW 34h, 1111111111011111b ; IRQ 5 + DW 38h, 1111111110111111b ; IRQ 6 + DW 3Ch, 1111111101111111b ; IRQ 7 + DW 1C0h, 1111111011111011b ; IRQ 8 + DW 1C4h, 1111110111111011b ; IRQ 9 + DW 1C8h, 1111101111111011b ; IRQ 10 + DW 1CCh, 1111011111111011b ; IRQ 11 + DW 1D0h, 1110111111111011b ; IRQ 12 + DW 1D4h, 1101111111111011b ; IRQ 13 + DW 1D8h, 1011111111111011b ; IRQ 14 + DW 1DCh, 0111111111111011b ; IRQ 15 + +IMR DW 0 + + CPF EQU 0 + PTRX EQU 20h + CVCF EQU 40h + VTFT EQU 60h + PSST EQU 0C0h + CSL EQU 0E0h + + CCCA EQU 100h + HWCF4 EQU 129h + HWCF5 EQU 12Ah + HWCF6 EQU 12Dh + SMALR EQU 134h + SMARR EQU 135h + SMALW EQU 136h + SMARW EQU 137h + SMLD EQU 43Ah + SMRD EQU 23Ah + WC EQU 23Bh + HWCF1 EQU 43Dh + HWCF2 EQU 43Eh + CFG2 EQU 43Eh + HWCF3 EQU 43Fh + INIT1 EQU 440h + INIT2 EQU 240h + INIT3 EQU 460h + INIT4 EQU 260h + ENVVOL EQU 480h + DCYSUSV EQU 4A0h + ENVVAL EQU 4C0h + DCYSUS EQU 4E0h + SUSDCY EQU 4E0h + ATKHLDV EQU 280h + LFO1VAL EQU 2A0h + ATKHLD EQU 2C0h + HLDATK EQU 2C0h + LFO2VAL EQU 2E0h + IP EQU 300h + IFATN EQU 320h + PEFE EQU 340h + FMMOD EQU 360h + TREMFRQ EQU 380h + FM2FRQ2 EQU 3A0h + +ALIGN 4 + +InitTable1 Label + DW 003FFh, 0030h, 007FFh, 0130h, 00BFFh, 0230h, 00FFFh, 0330h + DW 013FFh, 0430h, 017FFh, 0530h, 01BFFh, 0630h, 01FFFh, 0730h + DW 023FFh, 0830h, 027FFh, 0930h, 02BFFh, 0A30h, 02FFFh, 0B30h + DW 033FFh, 0C30h, 037FFh, 0D30h, 03BFFh, 0E30h, 03FFFh, 0F30h + + DW 043FFh, 0030h, 047FFh, 0130h, 04BFFh, 0230h, 04FFFh, 0330h + DW 053FFh, 0430h, 057FFh, 0530h, 05BFFh, 0630h, 05FFFh, 0730h + DW 063FFh, 0830h, 067FFh, 0930h, 06BFFh, 0A30h, 06FFFh, 0B30h + DW 073FFh, 0C30h, 077FFh, 0D30h, 07BFFh, 0E30h, 07FFFh, 0F30h + + DW 083FFh, 0030h, 087FFh, 0130h, 08BFFh, 0230h, 08FFFh, 0330h + DW 093FFh, 0430h, 097FFh, 0530h, 09BFFh, 0630h, 09FFFh, 0730h + DW 0A3FFh, 0830h, 0A7FFh, 0930h, 0ABFFh, 0A30h, 0AFFFh, 0B30h + DW 0B3FFh, 0C30h, 0B7FFh, 0D30h, 0BBFFh, 0E30h, 0BFFFh, 0F30h + + DW 0C3FFh, 0030h, 0C7FFh, 0130h, 0CBFFh, 0230h, 0CFFFh, 0330h + DW 0D3FFh, 0430h, 0D7FFh, 0530h, 0DBFFh, 0630h, 0DFFFh, 0730h + DW 0E3FFh, 0830h, 0E7FFh, 0930h, 0EBFFh, 0A30h, 0EFFFh, 0B30h + DW 0F3FFh, 0C30h, 0F7FFh, 0D30h, 0FBFFh, 0E30h, 0FFFFh, 0F30h + +InitTable2 Label + DW 003FFh, 8030h, 007FFh, 8130h, 00BFFh, 8230h, 00FFFh, 8330h + DW 013FFh, 8430h, 017FFh, 8530h, 01BFFh, 8630h, 01FFFh, 8730h + DW 023FFh, 8830h, 027FFh, 8930h, 02BFFh, 8A30h, 02FFFh, 8B30h + DW 033FFh, 8C30h, 037FFh, 8D30h, 03BFFh, 8E30h, 03FFFh, 8F30h + + DW 043FFh, 8030h, 047FFh, 8130h, 04BFFh, 8230h, 04FFFh, 8330h + DW 053FFh, 8430h, 057FFh, 8530h, 05BFFh, 8630h, 05FFFh, 8730h + DW 063FFh, 8830h, 067FFh, 8930h, 06BFFh, 8A30h, 06FFFh, 8B30h + DW 073FFh, 8C30h, 077FFh, 8D30h, 07BFFh, 8E30h, 07FFFh, 8F30h + + DW 083FFh, 8030h, 087FFh, 8130h, 08BFFh, 8230h, 08FFFh, 8330h + DW 093FFh, 8430h, 097FFh, 8530h, 09BFFh, 8630h, 09FFFh, 8730h + DW 0A3FFh, 8830h, 0A7FFh, 8930h, 0ABFFh, 8A30h, 0AFFFh, 8B30h + DW 0B3FFh, 8C30h, 0B7FFh, 8D30h, 0BBFFh, 8E30h, 0BFFFh, 8F30h + + DW 0C3FFh, 8030h, 0C7FFh, 8130h, 0CBFFh, 8230h, 0CFFFh, 8330h + DW 0D3FFh, 8430h, 0D7FFh, 8530h, 0DBFFh, 8630h, 0DFFFh, 8730h + DW 0E3FFh, 8830h, 0E7FFh, 8930h, 0EBFFh, 8A30h, 0EFFFh, 8B30h + DW 0F3FFh, 8C30h, 0F7FFh, 8D30h, 0FBFFh, 8E30h, 0FFFFh, 8F30h + +InitTable3 Label + DW 0C10h, 8470h, 14FEh, 0B488h, 167Fh, 0A470h, 18E7h, 84B5h + DW 1B6Eh, 842Ah, 1F1Dh, 852Ah, 0DA3h, 9F7Ch, 167Eh, 0F254h + DW 0, 842Ah, 1, 852Ah, 18E6h, 9BAAh, 1B6Dh, 0F234h + DW 229Fh, 8429h, 2746h, 8529h, 1F1Ch, 96E7h, 229Eh, 0F224h + + DW 0DA4h, 8429h, 2C29h, 8529h, 2745h, 97F6h, 2C28h, 0F254h + DW 383Bh, 8428h, 320Fh, 8528h, 320Eh, 9F02h, 1341h, 0F264h + DW 3EB6h, 8428h, 3EB9h, 8528h, 383Ah, 9FA9h, 3EB5h, 0F294h + DW 3EB7h, 8474h, 3EBAh, 8575h, 3EB8h, 0C4C3h, 3EBBh, 0C5C3h + + DW 00000, 0A404h, 00001, 0A504h, 141Fh, 8671h, 14FDh, 8287h + DW 3EBCh, 0E610h, 3EC8h, 8C7Bh, 31Ah, 87E6h, 3EC8h, 86F7h + DW 3EC0h, 821Eh, 3EBEh, 0D208h, 3EBDh, 821Fh, 3ECAh, 8386h + DW 3EC1h, 8C03h, 3EC9h, 831Eh, 3ECAh, 8C4Ch, 3EBFh, 8C55h + + DW 3EC9h, 0C208h, 3EC4h, 0BC84h, 3EC8h, 8EADh, 3EC8h, 0D308h + DW 3EC2h, 8F7Eh, 3ECBh, 821Eh, 3ECBh, 0D208h, 3EC5h, 831Fh + DW 3EC6h, 0C308h, 3EC3h, 0B2FFh, 3EC9h, 8265h, 3EC9h, 831Eh + DW 1342h, 0D308h, 3EC7h, 0B3FFh, 0, 8365h, 1420h, 9570h + +InitTable4 Label + DW 0C10h, 8470h, 14FEh, 0B488h, 167Fh, 0A470h, 18E7h, 84B5h + DW 1B6Eh, 842Ah, 1F1Dh, 852Ah, 0DA3h, 0F7Ch, 167Eh, 7254h + DW 0, 842Ah, 1, 852Ah, 18E6h, 0BAAh, 1B6Dh, 7234h + DW 229Fh, 8429h, 2746h, 8529h, 1F1Ch, 6E7h, 229Eh, 7224h + + DW 0DA4h, 8429h, 2C29h, 8529h, 2745h, 07F6h, 2C28h, 7254h + DW 383Bh, 8428h, 320Fh, 8528h, 320Eh, 0F02h, 1341h, 7264h + DW 3EB6h, 8428h, 3EB9h, 8528h, 383Ah, 0FA9h, 3EB5h, 7294h + DW 3EB7h, 8474h, 3EBAh, 8575h, 3EB8h, 44C3h, 3EBBh, 45C3h + + DW 00000, 0A404h, 00001, 0A504h, 141Fh, 0671h, 14FDh, 287h + DW 3EBCh, 0E610h, 3EC8h, 0C7Bh, 31Ah, 7E6h, 3EC8h, 86F7h + DW 3EC0h, 821Eh, 3EBEh, 0D208h, 3EBDh, 021Fh, 3ECAh, 386h + DW 3EC1h, 0C03h, 3EC9h, 31Eh, 3ECAh, 8C4Ch, 3EBFh, 0C55h + + DW 3EC9h, 0C208h, 3EC4h, 0BC84h, 3EC8h, 0EADh, 3EC8h, 0D308h + DW 3EC2h, 8F7Eh, 3ECBh, 021Eh, 3ECBh, 0D208h, 3EC5h, 31Fh + DW 3EC6h, 0C308h, 3EC3h, 32FFh, 3EC9h, 0265h, 3EC9h, 831Eh + DW 1342h, 0D308h, 3EC7h, 33FFh, 0, 8365h, 1420h, 9570h + +AWEVolumeTable Label Byte ; Value = -log(vol/256)*(20/.375) + ; = -log(vol/256)*(160/3) + + DB 255, 128, 112, 103, 96, 91, 87, 83 ; 0->7 + DB 80, 78, 75, 73, 71, 69, 67, 66 ; 8->15 + DB 64, 63, 61, 60, 59, 58, 57, 56 ; 16->23 + DB 55, 54, 53, 52, 51, 50, 50, 49 ; 24->31 + DB 48, 47, 47, 46, 45, 45, 44, 44 ; 32->39 + DB 43, 42, 42, 41, 41, 40, 40, 39 ; 40->47 + DB 39, 38, 38, 37, 37, 36, 36, 36 ; 48->55 + DB 35, 35, 34, 34, 34, 33, 33, 32 ; 56->63 + DB 32, 32, 31, 31, 31, 30, 30, 30 ; 64->71 + DB 29, 29, 29, 28, 28, 28, 28, 27 ; 72->79 + DB 27, 27, 26, 26, 26, 26, 25, 25 ; 80->87 + DB 25, 25, 24, 24, 24, 23, 23, 23 ; 88->95 + DB 23, 22, 22, 22, 22, 22, 21, 21 ; 96->103 + DB 21, 21, 20, 20, 20, 20, 20, 19 ; 104->111 + DB 19, 19, 19, 19, 18, 18, 18, 18 ; 112->119 + DB 18, 17, 17, 17, 17, 17, 16, 16 ; 120->127 + DB 16 ; 128 + + Comment ~ ; Value = -log(vol/128)*(20/.375) + ; = -log(vol/128)*(160/3) + ; This is mathematically the correct table, but it seems too + ; loud, and it overloads on playback. + + DB 255, 112, 96, 87, 80, 75, 71, 67 ; 0->7 + DB 64, 61, 59, 57, 55, 53, 51, 50 ; 8->15 + DB 48, 47, 45, 44, 43, 42, 41, 40 ; 16->23 + DB 39, 38, 37, 36, 35, 34, 34, 33 ; 24->31 + DB 32, 31, 31, 30, 29, 29, 28, 28 ; 32->39 + DB 27, 26, 26, 25, 25, 24, 24, 23 ; 40->47 + DB 23, 22, 22, 21, 21, 20, 20, 20 ; 48->55 + DB 19, 19, 18, 18, 18, 17, 17, 16 ; 56->63 + DB 16, 16, 15, 15, 15, 14, 14, 14 ; 64->71 + DB 13, 13, 13, 13, 12, 12, 12, 11 ; 72->79 + DB 11, 11, 10, 10, 10, 9, 9, 9 ; 80->87 + DB 9, 8, 8, 8, 8, 7, 7, 7 ; 88->95 + DB 7, 6, 6, 6, 6, 5, 5, 5 ; 96->103 + DB 5, 4, 4, 4, 4, 4, 4, 3 ; 104->111 + DB 3, 3, 3, 2, 2, 2, 2, 2 ; 112->119 + DB 1, 1, 1, 1, 1, 1, 1, 1 ; 120->127 + DB 0 + + ~ + +GUSScreenList Label + DW 7 + DW Near Ptr IdleFunctionList + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr GravisHeaderLine + + DW Near Ptr MixerText + DW Near Ptr VolumeBox1 + DW Near Ptr VolumeBox2 + + DW Near Ptr MasterVolumeLeft ; 7 + DW Near Ptr MasterVolumeRight + DW Near Ptr TrebleVolumeLeft + DW Near Ptr TrebleVolumeRight + DW Near Ptr BassVolumeLeft + DW Near Ptr BassVolumeRight ; 12 + + DW Near Ptr SampleText + + DW Near Ptr SampleSize0Button ; 14 + DW Near Ptr SampleSize1Button + DW Near Ptr SampleSize2Button + DW Near Ptr SampleSize3Button ; 17 + + DW Near Ptr EffectText + DW Near Ptr EffectBox + + DW Near Ptr ChorusThumbBar ; 20 + DW Near Ptr ReverbThumbBar + + DW DriverText + + DW 0 + +GravisHeaderLine DW 10 + DB "Sound Blaster AWE 32 Driver", 0 + +DriverText DW 1 + DB 27, 48 + DB 21h + DB "Sound Blaster AWE 32 Driver 1.5 for Impulse Tracker", 0 + +MixerText DW 1 + DB 3, 13 + DB 20h + DB "Mixer options", 13 + DB 13 + DB " Master Volume Left", 13 + DB " Master Volume Right", 13 + DB 13 + DB 13 + DB " Treble Left", 13 + DB " Treble Right", 13 + DB " Bass Left", 13 + DB " Bass Right", 13 + DB 0 + +VolumeBox1 DW 0 + DB 24, 14, 30, 17 + DB 25 + +VolumeBox2 DW 0 + DB 17, 18, 21, 23 + DB 25 + +MasterVolumeLeft DW 9 + DB 25, 15 + DW 0, 31 + DW 9, 0 + DW 0FFFFh, 8, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +MasterVolumeRight DW 9 + DB 25, 16 + DW 0, 31 + DW 9, 1 + DW 7, 9, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +TrebleVolumeLeft DW 9 + DB 18, 19 + DW 0, 15 + DW 9, 2 + DW 8, 10, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +TrebleVolumeRight DW 9 + DB 18, 20 + DW 0, 15 + DW 9, 3 + DW 9, 11, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +BassVolumeLeft DW 9 + DB 18, 21 + DW 0, 15 + DW 9, 4 + DW 10, 12, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +BassVolumeRight DW 9 + DB 18, 22 + DW 0, 15 + DW 9, 5 + DW 11, 14, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +SampleText DW 1 + DB 3, 25 + DB 20h + DB "Sample resizing options", 0 + +SampleSize0Button DW 2 + DW 12, 15, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetCompress +DriverSegment1 DW 0 + DW 0 + DW Offset SetCompress +DriverSegment2 DW 0 + DB 7, 27, 20, 29, 8 + DB 0 + DB " Original", 0 + +SampleSize1Button DW 2 + DW 14, 16, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetCompress +DriverSegment3 DW 0 + DW 1 + DW Offset SetCompress +DriverSegment4 DW 0 + DB 7, 30, 20, 32, 8 + DB 0 + DB " Half", 0 + +SampleSize2Button DW 2 + DW 15, 17, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetCompress +DriverSegment5 DW 0 + DW 2 + DW Offset SetCompress +DriverSegment6 DW 0 + DB 7, 33, 20, 35, 8 + DB 0 + DB " Quarter", 0 + +SampleSize3Button DW 2 + DW 16, 20, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetCompress +DriverSegment7 DW 0 + DW 3 + DW Offset SetCompress +DriverSegment8 DW 0 + DB 7, 36, 20, 38, 8 + DB 0 + DB " Eighth", 0 + +EffectText DW 1 + DB 3, 40 + DB 20h + DB "Effect options", 13 + DB 13 + DB " Chorus", 13 + DB " Reverb", 0 + + +EffectBox DW 0 + DB 12, 41, 30, 44 + DB 25 + +ChorusThumbBar DW 9 + DB 13, 42 + DW 0, 127 + DW 9, 6 + DW 17, 21, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +ReverbThumbBar DW 9 + DB 13, 43 + DW 0, 127 + DW 9, 7 + DW 20, 0FFFFh, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + + + +VolumeTable DB 6 Dup (0) +CONFIGURATIONOFFSET EQU $+128 +CONFIGSIZE EQU 2 +Chorus DB 10, 64 + +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +IdleFunctionList DD 0 + DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +ALIGN 16 +FPSave DB 128 Dup (0) + +AWEParameters DB 64 Dup (0FFh), 64 Dup (0) + +include dma.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SBOut ; AL = data + ; DX = 2xCh + + Push AX + +SBOut1: + In AL, DX + Test AL, AL + JS SBOut1 + + Pop AX + Out DX, AL + + Ret + +EndP SBOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UARTOut + + Push CX + Push DX + Mov DX, CS:MIDIPort + Test DX, DX + JZ UARTOutEnd + + Push AX + Xor CX, CX + Inc DX + +UARTOut1: + In AL, DX + Test AL, 40h + LoopNZ UARTOut1 + + Pop AX + JNZ UARTOutEnd + + Dec DX + Out DX, AL + +UARTOutEnd: + Pop DX + Pop CX + + Ret + +EndP UARTOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + + +InterpretState DB 0 +InterpretType DB 0 + +Proc SendUARTOut Far ; Local interpreter activated with 0F0h 0F0h. + + Mov AH, CS:InterpretState + Cmp AH, 2 + JB SendUARTOut1 + +; In interpreter. + JE SendUARTOut3 + +; Have InterpretType, now get parameter, then return to normal. + + Push BX + + Mov BL, CS:InterpretType ; Want BX = InterpretType*64+Channel + ; + ShL BX, 6 + Add BL, [DI+20h] + And BX, 127 + Mov [CS:AWEParameters+BX], AL + + Pop BX + + Mov CS:InterpretState, 0 + + Test SI, SI + JZ SendUARTOut4 + + Or Byte Ptr [SI], 64 + +SendUARTOut4: + Ret + +SendUARTOut3: + Mov InterpretType, AL + Jmp SendUARTOutStateInc + +SendUARTOut1: + Cmp AL, 0F0h + JNE SendUARTOut2 + +SendUARTOutStateInc: + Inc CS:InterpretState + Ret + +SendUARTOut2: + Test AH, AH + JZ SendUARTOutEnd + + Push AX + Mov AL, 0F0h + Call UARTOut + Pop AX + Mov CS:InterpretState, 0 + +SendUARTOutEnd: + Cmp AL, 0FCh + JE ResetFilters + Cmp AL, 0FAh + JE ResetFilters + + Cmp AL, 0FFh + JNE SendUARTOutNoClear + +ResetFilters: + PushA + Push ES + + Push CS + Pop ES + + Mov DI, Offset AWEParameters + Mov CX, 32 + Or AX, -1 + Rep StosW + Mov CX, 32 + Inc AX + Rep StosW + + Pop ES + PopA + +SendUARTOutNoClear: + Call UARTOut + Ret + +EndP SendUARTOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectUART ; Given DX = Port + +; outportb(BasePort+1, 0xFF); +; while(InputUART() != 0xFE); +; outportb(BasePort+1, 0x3F); +; while(InputUART() != 0xFE); + + ClI + + Inc DX + Mov AL, 0FFh ; reset + Out DX, AL + Xor CX, CX + +DetectUART1: + In AL, DX + Test AL, 80h + LoopNZ DetectUART1 + JNZ DetectUARTFailed + + Dec DX + In AL, DX + Inc DX + Cmp AL, 0FEh + JNE DetectUART1 + + Xor CX, CX + +DetectUART3: + In AL, DX + Test AL, 40h + LoopNZ DetectUART3 + JNZ DetectUARTFailed + + Mov AL, 03Fh + Out DX, AL + + Xor CX, CX + +DetectUART2: + In AL, DX + Test AL, 80h + LoopNZ DetectUART2 + JNZ DetectUARTFailed + + Dec DX + In AL, DX + Inc DX + Cmp AL, 0FEh + JNE DetectUART2 + Dec DX + + ClC + StI + Ret + +DetectUARTFailed: + StC + StI + Ret + +Comment ~ + +; From SB-DevKit + + ClI + + Inc DX + Xor CX, CX + +DetectUART1: + In AL, DX + Test AL, 40h ; Ready for output + LoopNZ DetectUART1 + JNZ DetectUARTError + + Mov AL, 0FFh ; Reset! + Out DX, AL + + Xor CX, CX + +DetectUART2: + In AL, DX + Test AL, 80h + JNZ DetectUART3 + + Dec DX + In AL, DX + Inc DX + Cmp AL, 0FEh + JE DetectUART4 + +DetectUART3: + Loop DetectUART2 + +DetectUARTError: + StI + StC + Ret + +DetectUART4: ; Now to shove it into 'intelligent' mode. + Xor CX, CX + +DetectUART5: + In AL, DX + Test AL, 40h + LoopNZ DetectUART5 + JNZ DetectUARTError + + Mov AL, 3Fh ; Intelligent mode! + Out DX, AL + +DetectUART6: + Xor CX, CX + +DetectUART7: + In AL, DX + Test AL, 80h + JNZ DetectUART8 + + Dec DX + In AL, DX + Inc DX + Cmp AL, 0FEh + JE DetectUART9 + +DetectUART8: + Loop DetectUART7 + + Jmp DetectUARTError + +DetectUART9: + StI + ClC + Ret + +~ + +EndP DetectUART + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReinitUART + + Mov DX, MIDIPort + Test DX, DX + JZ ReinitUART1 + + Call DetectUART + +ReinitUART1: + Ret + +EndP ReinitUART + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetUART + + Mov DX, MIDIPort + Test DX, DX + JZ ResetUART1 + + Inc DX + + Mov AL, 0FFh + Out DX, AL + +ResetUART1: + Ret + +EndP ResetUART + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetCompress Far + + Mov CX, [SI+22] + Mov CS:Compress, CL + + Mov AX, 1 + ShL AX, CL + Mov CS:Step, AX + + Call Music_LoadAllSamples + + Mov AX, 1 + Ret + +EndP SetCompress + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetCompress Far + + Push CS + Pop ES + Mov DI, Offset Compress + + Ret + +EndP GetCompress + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Load8BitSamplesForwards ; Given DS:SI, ECX = count + + Push BX + + Mov BX, CS:Step + Mov DX, CS:BasePort + Add DX, 400h + Xor AL, AL + +Load8BitSamplesForwards2: + Mov AH, [SI] + Add SI, BX + JC Load8BitSamplesForwards4 + +Load8BitSamplesForwards3: + Out DX, AX + + Dec ECX + JNZ Load8BitSamplesForwards2 + + Pop BX + Ret + +Load8BitSamplesForwards4: + Add ESI, 10000h + Int 3 + Jmp Load8BitSamplesForwards3 + +EndP Load8BitSamplesForwards + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Load16BitSamplesForwards ; Given DS:SI, ECX = count + + Push BX + + Mov BX, CS:Step + Mov DX, CS:BasePort + Add DX, 400h + Add BX, BX + +Load16BitSamplesForwards2: + Mov AX, [SI] + Add SI, BX + JC Load16BitSamplesForwards4 + +Load16BitSamplesForwards3: + Out DX, AX + + Dec ECX + JNZ Load16BitSamplesForwards2 + + Pop BX + Ret + +Load16BitSamplesForwards4: + Add ESI, 10000h + Int 3 + Jmp Load16BitSamplesForwards3 + +EndP Load16BitSamplesForwards + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Load8BitSamplesBackwards ; Given DS:SI, ECX = count + + Push BX + + Mov BX, CS:Step + Mov DX, CS:BasePort + Add DX, 400h + Xor AL, AL + + Sub SI, BX + JC Load8BitSamplesBackwards6 + +Load8BitSamplesBackwards2: + Sub SI, BX + JC Load8BitSamplesBackwards4 + +Load8BitSamplesBackwards3: + Mov AH, [SI] + Out DX, AX + + Dec ECX + JNZ Load8BitSamplesBackwards2 + + + Pop BX + Ret + +Load8BitSamplesBackwards4: + Sub ESI, 10000h + JC Load8BitSamplesBackwards5 + Int 3 + Jmp Load8BitSamplesBackwards3 + +Load8BitSamplesBackwards5: + Xor ESI, ESI + Jmp Load8BitSamplesBackwards3 + +Load8BitSamplesBackwards6: + Sub ESI, 10000h + Int 3 + Jmp Load8BitSamplesBackwards2 + + +EndP Load8BitSamplesBackwards + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Load16BitSamplesBackwards ; Given DS:SI, ECX = count + + Push BX + + Mov BX, CS:Step + Mov DX, CS:BasePort + Add DX, 400h + Add BX, BX + + Sub SI, BX + JC Load16BitSamplesBackwards6 + +Load16BitSamplesBackwards2: + Sub SI, BX + JC Load16BitSamplesBackwards4 + +Load16BitSamplesBackwards3: + Mov AX, [SI] + Out DX, AX + + Dec ECX + JNZ Load16BitSamplesBackwards2 + + Pop BX + Ret + +Load16BitSamplesBackwards4: + Sub ESI, 10000h + JC Load16BitSamplesBackwards5 + Int 3 + Jmp Load16BitSamplesBackwards3 + +Load16BitSamplesBackwards5: + Xor ESI, ESI + Jmp Load16BitSamplesBackwards3 + +Load16BitSamplesBackwards6: + Sub ESI, 10000h + Int 3 + Jmp Load16BitSamplesBackwards2 + + +EndP Load16BitSamplesBackwards + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WriteDataChannel + + Or AX, DX + +Proc WriteData ; Have BX/EBX = value + ; AX = xxyyh + ; ^ ^ + ; | | + ; | \-- value to send to pointer register + ; \---- 0, 1, 2 or 3, 4 + ; 0 = data reg 0 + ; 1 = data reg 1, dword + ; 2 = data reg 2 + ; 3 = data reg 3 + ; 4 = data reg 4, word + + Jmp $+2 + Jmp $+2 + + Push DX + Push AX + + Mov DX, BasePort + Add DX, 802h + And AX, 0FFh + Out DX, AX + Pop AX + + Jmp $+2 + Jmp $+2 + + Cmp AH, 1 + JB WriteDataReg0 + JE WriteDataReg1DWord + Cmp AH, 3 + JB WriteDataReg2 + JE WriteDataReg3 + Jmp WriteDataReg1Word + +WriteDataReg0: + Sub DX, 802h + Mov EAX, EBX + Out DX, EAX + + Pop DX + Ret + +WriteDataReg1DWord: + Sub DX, 402h + Mov EAX, EBX + Out DX, EAX + + Pop DX + Ret + +WriteDataReg1Word: + Sub DX, 402h + Mov AX, BX + Out DX, AX + + Pop DX + Ret + +WriteDataReg2: + Sub DX, 400h + Mov AX, BX + Out DX, AX + + Pop DX + Ret + +WriteDataReg3: + Sub DL, 2 + Mov AX, BX + Out DX, AX + + Pop DX + Ret + +EndP WriteData + +EndP WriteDataChannel + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReadDataChannel + + Or AX, DX + +Proc ReadData ; AX = xxyyh + ; ^ ^ + ; | | + ; | \-- value to send to pointer register + ; \---- 0, 1, 2 or 3, 4 + ; 0 = data reg 0 + ; 1 = data reg 1, dword + ; 2 = data reg 2 + ; 3 = data reg 3 + ; 4 = data reg 4, word + + Jmp $+2 + Jmp $+2 + + Push DX + Push AX + + Mov DX, BasePort + Add DX, 802h + And AX, 0FFh + Out DX, AX + Pop AX + + Jmp $+2 + Jmp $+2 + + Cmp AH, 1 + JB ReadDataReg0 + JE ReadDataReg1DWord + Cmp AH, 3 + JB ReadDataReg2 + JE ReadDataReg3 + Jmp ReadDataReg1Word + +ReadDataReg0: + Sub DX, 802h + In EAX, DX + + Pop DX + Ret + +ReadDataReg1DWord: + Sub DX, 402h + In EAX, DX + + Pop DX + Ret + +ReadDataReg1Word: + Sub DX, 402h + In AX, DX + + Pop DX + Ret + +ReadDataReg2: + Sub DX, 400h + In AX, DX + + Pop DX + Ret + +ReadDataReg3: + Sub DL, 2 + In AX, DX + + Pop DX + Ret + +EndP ReadData + +EndP ReadDataChannel + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Const44100 DD 44100.0 +Const1000h DD 4096.0 +ConstE000h DD 57344.0 + +Proc SetAWEFrequency + + Mov EAX, [SI+10h] ; Final freq + + Push CX + Mov CL, Compress + ShR EAX, CL + Pop CX + +; Test EAX, EAX + JZ SetAWEFrequencyError + Cmp EAX, 88200*2 + JAE SetAWEFrequencyError + + Mov DWord Ptr [SI+4], EAX + + FLd CS:ConstE000h + FLd CS:Const1000h + FILd DWord Ptr [SI+4] + FDiv CS:Const44100 + FYL2X ; ST = ln(Pitch/44100)/ln(2) * 1000h + FAddP ST(1) + FIStP DWord Ptr [SI+4] + + Mov AX, IP + Mov BX, [SI+4] + Call WriteDataChannel + + Ret + Assume DS:Nothing + +SetAWEFrequencyError: + Call StopAWENote + + Mov Word Ptr [SI], 200h + Test Byte Ptr [SI+3Ah], 80h + JNZ SetAWEFrequencyError1 + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Signify channel off + +SetAWEFrequencyError1: + Mov AX, IP + Xor EBX, EBX + Call WriteDataChannel + + Push DS SI + + Push CS + Pop DS + Mov SI, Offset FrequencyError + Mov BX, 40 + Call SetInfoLine + + Pop SI DS + + Ret + +EndP SetAWEFrequency + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetAWEPan + + Mov AX, PSST + Call ReadDataChannel ; Get starting offset + + Cmp CS:Stereo, 0 + JE SetPan2 + + Test CL, 128 + JNZ SetPan2 + + Mov BL, [SI+37h] ; Final pan + Cmp BL, 100 ; Surround -> central + JNE SetPan1 + +SetPan2: + Mov BL, 32 + +SetPan1: ; BL = 0->64, need to extend to 0->255 + Add BL, BL + Add BL, BL + SBB BL, 0 ; BL = 0->255 + Not BL + + ShL EAX, 8 + SHLD EBX, EAX, 24 + Mov AX, PSST + Call WriteDataChannel + + Ret + +EndP SetAWEPan + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetAWEVolume + + Test CH, 8 + JZ SetAWEVolume1 + + Test CH, 1 + JNZ SetAWEVolume5 + + Cmp Byte Ptr [SI+8], 0FFh + JE SetAWEVolume4 + +SetAWEVolume5: + Mov Byte Ptr [SI+8], 0FFh + + Mov AX, IFATN + Call ReadDataChannel + Mov BX, AX + Mov AX, IFATN + Mov BL, 0FFh + Call WriteDataChannel + +SetAWEVolume4: + Ret + +SetAWEVolume1: +; First check if channel has been disowned + Xor BX, BX + Mov BL, [SI+3Ah] ; BL = host channel + + Test BL, BL + JS SetAWEVolume3 + +SetAWEVolume2: + Mov AH, [CS:AWEParameters+BX] ; AH = filter + Mov AL, [CS:AWEParameters+BX+64] ; AL = Q. + + ShR AL, 3 + Mov [SI+5Bh], AH + + Cmp AL, [SI+3Fh] + JE SetAWEVolume3 + + Mov [SI+3Fh], AL + +; Set Q + Mov BL, AL + ShL EBX, 28 + + Mov AX, CCCA + Call ReadDataChannel + And EAX, 0FFFFFFFh + Or EBX, EAX + Mov AX, CCCA + Call WriteDataChannel + +SetAWEVolume3: + Mov AL, [SI+3Eh] + Mul Byte Ptr [SI+5Bh] + ShL AX, 1 + Xor BX, BX + Add AH, 1 + Mov BL, [SI+20h] ; Final volume + Mov [SI+8], BL + Mov BL, [CS:AWEVolumeTable+BX] + Mov BH, AH + Mov AX, IFATN + Call WriteDataChannel + + Ret + +EndP SetAWEVolume + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StopAWENote + + Mov AX, DCYSUSV + Mov BX, 80h + Call WriteDataChannel + + Mov AX, VTFT + Mov EBX, 0FFFFh + Call WriteDataChannel + + Mov AX, CVCF + Call WriteDataChannel + + Mov BX, 80h + Mov AX, DCYSUSV + Call WriteDataChannel + + Mov AX, VTFT + Mov EBX, 0FFFFh + Call WriteDataChannel + + Mov AX, CVCF + Call WriteDataChannel + + Xor EBX, EBX + Mov AX, ENVVOL + Call WriteDataChannel + + Mov AX, ENVVAL + Call WriteDataChannel + + Mov AX, SUSDCY + Call WriteDataChannel + + Mov AX, ATKHLDV + Call WriteDataChannel + + Mov AX, LFO1VAL + Call WriteDataChannel + + Mov AX, HLDATK + Call WriteDataChannel + + Mov AX, LFO2VAL + Call WriteDataChannel + + Mov AX, IP + Call WriteDataChannel + + Mov AX, IFATN + Call ReadDataChannel + Mov BH, AH + Mov AX, IFATN + Call WriteDataChannel + + Xor EBX, EBX + Mov AX, PEFE + Call WriteDataChannel + + Mov AX, FMMOD + Call WriteDataChannel + + Mov AX, TREMFRQ + Call WriteDataChannel + + Mov AX, FM2FRQ2 + Call WriteDataChannel + + Mov AX, PTRX + Call WriteDataChannel + + Mov AX, VTFT + Call WriteDataChannel + +; Mov AX, PSST +; Call WriteDataChannel + + Mov BL, 8 + Mov AX, CSL + Call WriteDataChannel + + Mov AX, CCCA + Call ReadDataChannel + Mov EBX, EAX + Mov AX, CCCA + And EBX, 0F0000000h + Call WriteDataChannel + + Xor EBX, EBX + Mov AX, CPF + Call WriteDataChannel + + Ret + +EndP StopAWENote + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetAWERegisters ; DS:SI = channel info table + ; CX = number of channels... + + Push CX + Push SI + + ; Stage 1. + ; Turn off any channel which has + ; a new note to play + ; If no new note to play and channel + ; is on, then get current position + + Xor DX, DX ; DX = oscillator number + +GetAWERegisters1: + Mov BX, [SI] + Test BH, 2 ; Note cut command + JZ GetAWERegisters2 + + Mov BX, 200h + Mov [SI], BX + + Call StopAWENote + Jmp GetAWERegisters4 + +GetAWERegisters2: + Test BL, 1 ; Channel on? + JZ GetAWERegisters4 + + Test BH, 1 ; New note? + JZ GetAWERegisters3 + + ; Fade out volume +; Mov AX, DCYSUSV +; Mov BX, 807Fh +; Call WriteDataChannel + + Call StopAWENote + + Jmp GetAWERegisters4 + +GetAWERegisters3: ; Get offset + Mov AX, CCCA + Call ReadDataChannel + + Xor BX, BX + And EAX, 00000000111111111111111111111111b + Inc EAX ; Interpolator correction + ; EAX = address in sound memory + Mov BL, [SI+36h] ; BL = sample number + LEA BX, [EBX*4+EBX] + ShL BX, 2 + Add BX, Offset AWEDataTable + + Cmp Byte Ptr [SI+0Ah], 8 + JB GetAddressNoLoop + JE GetAddressForwardsLoop + +GetAddressPingPongLoop: + Cmp EAX, [CS:BX+16] + JB SetOldAddress + + Neg EAX + Add EAX, [CS:BX+8] + Jmp SetOldAddress1 + +GetAddressNoLoop: + Cmp EAX, [CS:BX+4] ; Start loop + JB SetOldAddress + + Call StopAWENote + + ; OK.. gotta turn off channel + Mov Word Ptr [SI], 0 + Test Byte Ptr [SI+3Ah], 80h + JNZ GetAWERegisters4 + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Signify channel off + + Jmp GetAWERegisters4 + +GetAddressForwardsLoop: +SetOldAddress: + Sub EAX, [CS:BX] ; EAX = address in sample + JNS SetOldAddress1 + + Xor EAX, EAX + +SetOldAddress1: + Push CX + Mov CL, Compress + ShL EAX, CL + Pop CX + + XChg [SI+4Ch], EAX + Mov [SI+2Ch], EAX + +GetAWERegisters4: + Add SI, 128 + + Inc DX + Dec CX + JNZ GetAWERegisters1 + + Pop SI + Pop CX + + Xor DX, DX ; DX = oscillator number + +SetAWERegisters1: + ; Stage 2. + ; If new frequency, play new frequency + ; If new volume, play new volume + ; If new pan, play new pan + ; If new note, set ENVVOL, ENVVAL, SUSDCY, ATKHLDV, LFO1VAL, HLDATK + ; LFO2VAL, IP, IFATN, PEFE, FMMOD, TREMFRQ, FM2FRQ2 + ; PSST, CSL, CCCA + ; VTFT, CVCF, DCYSUSV, PTRX, CPF + + Push CX + Mov CX, [SI] + Test CL, 1 ; Channel on? + JZ SetAWERegistersEnd + + Test CH, 1 ; New note? + JZ SetAWERegisters2 + + Xor BX, BX + Mov BL, [SI+36h] + LEA DI, [EBX*4+EBX] + ShL DI, 2 + Add DI, Offset AWEDataTable + + Mov AX, DCYSUSV + Mov BX, 80h + Call WriteDataChannel + + Mov AX, VTFT + Xor EBX, EBX + Call WriteDataChannel + + Mov AX, CVCF + Call WriteDataChannel + + Cmp DWord Ptr [CS:DI], 0FFFFFFFFh + JE SetAWERegistersError + + Mov AX, PTRX + Call WriteDataChannel + + Mov AX, CPF + Call WriteDataChannel + + + Mov AX, ENVVOL + Mov BX, 8000h + Call WriteDataChannel + + Mov AX, ENVVAL + Mov BX, 8000h + Call WriteDataChannel + + Mov AX, SUSDCY + Mov BX, 7F7Fh + Call WriteDataChannel + + Mov AX, ATKHLDV + Call WriteDataChannel + + Mov AX, LFO1VAL + Mov BX, 8000h + Call WriteDataChannel + + Mov AX, HLDATK + Mov BX, 7F7Fh + Call WriteDataChannel + + Mov AX, LFO2VAL + Mov BX, 8000h + Call WriteDataChannel + + Call SetAWEFrequency + Call SetAWEVolume + + Mov AX, PEFE + Xor BX, BX + Call WriteDataChannel + + Mov AX, FMMOD + Call WriteDataChannel + + Mov AX, TREMFRQ + Mov BX, 10h + Call WriteDataChannel + + Mov AX, FM2FRQ2 + Call WriteDataChannel + + + Mov EBX, [CS:DI+4] + Dec EBX ; Interpolator offset + Mov AX, PSST + Call WriteDataChannel + + Call SetAWEPan + + Mov AL, [CS:VolumeTable+6] ; Chorus + ShL EAX, 24 + Mov EBX, [CS:DI+8] + Dec EBX ; Interpolator offset + Or EBX, EAX + Mov AX, CSL + Call WriteDataChannel + + Mov AL, [SI+3Fh] + ShL EAX, 28 + + Push CX + Mov CL, Compress + Mov EBX, [SI+4Ch] + ShR EBX, CL + Pop CX + Add EBX, [CS:DI] + Dec EBX ; Interpolator offset + Or EBX, EAX + + Mov AX, CCCA ; Current address. + Call WriteDataChannel + + + Mov AX, VTFT + Mov EBX, 0FFFFh + Call WriteDataChannel + + Mov AX, CVCF + Call WriteDataChannel + + Mov AX, DCYSUSV + Mov BX, 7F7Fh + Call WriteDataChannel + + Mov AX, PTRX + Mov EBX, 40000000h ; 25% reverb + Or BH, [CS:VolumeTable+7] + Call WriteDataChannel + + Mov AX, CPF + Call WriteDataChannel + Jmp SetAWERegistersEnd + +SetAWERegisters2: + Test CL, 32 ; Frequency change? + JZ SetAWERegisters3 + + Call SetAWEFrequency + +SetAWERegisters3: + Test CL, 64 ; Volume change? + JZ SetAWERegisters4 + + Call SetAWEVolume + +SetAWERegisters4: + Test CH, 80h ; New pan? + JZ SetAWERegistersEnd + + Call SetAWEPan + +SetAWERegistersEnd: + Pop CX + And Word Ptr [SI], 0111100010011111b + + Add SI, 128 + + Inc DX + Dec CX + JNZ SetAWERegisters1 + + Ret + +SetAWERegistersError: + Call StopAWENote + + Mov Word Ptr [SI], 0 + Test Byte Ptr [SI+3Ah], 80h + JNZ SetAWERegistersEnd + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Signify channel off + + Jmp SetAWERegistersEnd + +EndP SetAWERegisters + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ACKIRQ + + Mov AL, 20h + Cmp CS:IRQ, 7 + JBE ACKIRQ1 + + Out 0A0h, AL + +ACKIRQ1: + Out 20h, AL + Ret + +EndP ACKIRQ + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc CheckMIDI + + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Xor BX, BX + Mov DX, MIDIPort + + Mov BL, [MIDIBufferTail] + Test DX, DX + JZ CheckMIDIEnd + + Inc DX + +CheckMIDIAgain: + In AL, DX + + Test AL, AL + JS CheckMIDIAgain + + Dec DX + In AL, DX + + Cmp AL, 0F0h + JAE CheckMIDIEnd + + Inc BL + Cmp BL, MIDIBufferHead + JE CheckMIDIEnd + + Mov [MIDIBuffer+BX], AL + Mov [MIDIBufferTail], BL + +CheckMIDIEnd: + Pop DS + Ret + +EndP CheckMIDI + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc MIDIIRQHandler + + Push AX BX DX + + Mov DX, CS:MixerPort + Mov AL, 82h + Out DX, AL + Inc DL + In AL, DX + + Test AL, 4 + JZ MIDIIRQHandlerEnd + + Call CheckMIDI + +MIDIIRQHandlerEnd: + Call AckIRQ + + Pop DX BX AX + IRet + + +EndP MIDIIRQHandler + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SBIRQHandler + + PushAD + Push DS + Push ES + + StI + + Push CS + Pop DS + Assume DS:Driver + + FNSave [FPSave] + +SBIRQHandlerAgain: + Mov DX, MixerPort + Mov AL, 82h + Out DX, AL + Inc DL + In AL, DX + + Test AL, 4 + JZ NoMIDIIRQ + + Push AX + Call CheckMIDI + Pop AX + +NoMIDIIRQ: +; Test AL, 2 +; JZ No16BitIRQ +; +; Push AX +; Mov DX, MixerPort +; Add DL, 0Fh-4 +; In AL, DX +; Pop AX +; +; No16BitIRQ: + Test AL, 1 + JNZ SB8BitIRQ + +SBNo8BitIRQ: + Call AckIRQ + Jmp SBEndIRQ + +SB8BitIRQ: + Mov DX, MixerPort + Add DL, 0Eh-4 + In AL, DX ; 8-bit IRQ ack. + + +; Add DL, 0Ch-0Eh + +; Mov AL, 80h ; Output block of silence +; Call SBOut +; Mov AX, BlockLength2 +; Call SBOut +; Mov AL, AH +; Call SBOut + + ClD + Call ACKIRQ + + Inc IRQFlag + JNZ SBEndIRQ + + Call SaveEMSPageFrame + Assume DS:Nothing + +SB8BitIRQAgain: + Call Update ; Returns DS:SI, CX + + Mov BX, BlockLength + Cmp BX, BlockLength2 + JE SBIRQHandler2 + Mov BlockLength2, BX + + Mov DX, SB16BasePort + Add DL, 0Ch + + MOv AL, 0DAh + Call SBOut + Mov AL, 0C6h + Call SBOut + Xor AL, AL + Call SBOut + Mov AL, BL + Call SBOut + Mov AL, BH + Call SBOut + +; Mov AL, 0D0h +; Call SBOut + +; Mov AL, 80h ; Output block of silence +; Call SBOut +; Mov AL, BL +; Call SBOut +; Mov AL, BH +; Call SBOut + +SBIRQHandler2: + Call SetAWERegisters + Sub CS:IRQFlag, 1 + JNC SB8BitIRQAgain + + Call RestoreEMSPageFrame + +SBEndIRQ: + FRstor [CS:FPSave] + + Pop ES + Pop DS + PopAD + + IRet + +EndP SBIRQHandler + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc AWEIRQHandler ; IRQ Handler has to + ; 1) Update AWE registers + ; 2) Update song position + Push AX + Push DS + + Mov AX, AWEUpdateTimer + Add AWEUpdateCount, AX + JC AWEIRQHandler1 + + Mov AL, 20h + Out 20h, AL + Jmp AWEIRQHandler2 + +AWEIRQHandler1: + PushF + Call [OldIRQHandler] + +AWEIRQHandler2: + Xor AWEUpdateFlag, 1 + JZ AWEIRQHandlerEnd + + FNSave [CS:FPSave] + + PushAD + Push ES + + ClD + + Call SaveEMSPageFrame + Call Update ; Returns DS:SI, CX + Call SetAWERegisters + Call RestoreEMSPageFrame + + Pop ES + PopAD + + FRstor [CS:FPSave] + +AWEIRQHandlerEnd: + Pop DS + Pop AX + IRet + +EndP AWEIRQHandler + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc EnableRAM + + Mov DX, BasePort + Mov CX, 29 + +EnableRAM1: + Mov AX, DCYSUSV + Or AX, CX + Mov BX, 80h + Call WriteData + + Mov AX, VTFT + Or AX, CX + Xor EBX, EBX + Call WriteData + + Mov AX, CVCF + Or AX, CX + Xor EBX, EBX + Call WriteData + + Mov AX, PTRX + Or AX, CX + Mov EBX, 40000000h + Call WriteData + + Mov AX, CPF + Or AX, CX + Mov EBX, 40000000h + Call WriteData + + Mov AX, PSST + Or AX, CX + Xor EBX, EBX + Call WriteData + + Mov AX, CSL + Or AX, CX + Xor EBX, EBX + Call WriteData + + Mov AX, CCCA + Or AX, CX + Mov EBX, 6000000h ; Left write + Call WriteData + + Dec CX + JNS EnableRAM1 + + Ret + +EndP EnableRAM + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc TestAWE ; Given DX = baseport. + + Push DX + + Add DX, 802h + In AL, DX + In AL, DX + Not AL + Mov BL, AL + Out DX, AL + In AL, DX + Cmp AL, BL + JNE TestAWE1 ; Register changed + + In AX, DX ; Is upper part of pointer + Mov BX, AX ; changing? + Mov CX, 128 + +TestAWE2: + In AX, DX + Cmp AL, BL + JNE TestAWE1 + Cmp AH, BH + JNE TestAWE3 + + Dec CX + JNZ TestAWE2 + Jmp TestAWE1 + +TestAWE3: + Pop DX + + ClC + Ret + +TestAWE1: + Pop DX + StC + Ret + +EndP TestAWE + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSetAWE + + Mov CX, 31 + +InitSetAWE1: + Mov AX, 31 + Sub AX, CX + Mov BX, [SI] + Or AX, INIT1 + Call WriteData + + Add SI, 2 + + Dec CX + JNS InitSetAWE1 + + Mov CX, 31 + +InitSetAWE2: + Mov AX, 31 + Sub AX, CX + Mov BX, [SI] + Or AX, INIT2 + Call WriteData + + Add SI, 2 + + Dec CX + JNS InitSetAWE2 + + Mov CX, 31 + +InitSetAWE3: + Mov AX, 31 + Sub AX, CX + Mov BX, [SI] + Or AX, INIT3 + Call WriteData + + Add SI, 2 + + Dec CX + JNS InitSetAWE3 + + Mov CX, 31 + +InitSetAWE4: + Mov AX, 31 + Sub AX, CX + Mov BX, [SI] + Or AX, INIT4 + Call WriteData + + Add SI, 2 + + Dec CX + JNS InitSetAWE4 + + Ret + +EndP InitSetAWE + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitAWE + + Push CS + Pop DS + Assume DS:Driver + + Mov DX, BasePort + + Mov AX, HWCF1 + Mov BX, 59h + Call WriteData + + Mov AX, CFG2 + Mov BX, 20h + Call WriteData + + Mov CX, 31 + +InitAwe1: + Mov BX, 80h + Mov AX, DCYSUSV + Or AX, CX + Call WriteData + + Xor EBX, EBX + Mov AX, ENVVOL + Or AX, CX + Call WriteData + + Mov AX, ENVVAL + Or AX, CX + Call WriteData + + Mov AX, SUSDCY + Or AX, CX + Call WriteData + + Mov AX, ATKHLDV + Or AX, CX + Call WriteData + + Mov AX, LFO1VAL + Or AX, CX + Call WriteData + + Mov AX, HLDATK + Or AX, CX + Call WriteData + + Mov AX, LFO2VAL + Or AX, CX + Call WriteData + + Mov AX, IP + Or AX, CX + Call WriteData + + Mov AX, IFATN + Or AX, CX + Call WriteData + + Mov AX, PEFE + Or AX, CX + Call WriteData + + Mov AX, FMMOD + Or AX, CX + Call WriteData + + Mov AX, TREMFRQ + Or AX, CX + Call WriteData + + Mov AX, FM2FRQ2 + Or AX, CX + Call WriteData + + Mov AX, PTRX + Or AX, CX + Call WriteData + + Mov AX, VTFT + Or AX, CX + Call WriteData + + Mov AX, PSST + Or AX, CX + Call WriteData + + Mov AX, CSL + Or AX, CX + Call WriteData + + Mov AX, CCCA + Or AX, CX + Call WriteData + + Dec CX + JNS InitAWE1 + + Mov CX, 31 + +InitAWE8: + Mov AX, CPF + Or AX, CX + Call WriteData + + Mov AX, CVCF + Or AX, CX + Call WriteData + + Dec CX + JNS InitAWE8 + ; Initialise still... + Mov AX, SMALR + Call WriteData + + Mov AX, SMARR + Call WriteData + + Mov AX, SMALW + Call WriteData + + Mov AX, SMARW + Call WriteData + + Mov SI, Offset InitTable1 + Call InitSetAWE + + ; Wait for 1024 sample periods + Mov AX, WC + Call ReadData + + Mov BX, AX + Mov CX, AX + Add CX, 400h ; 1024 + Cmp BX, CX + JB InitAWE3 + +InitAWE4: + Mov AX, WC + Call ReadData + Cmp AX, CX + JA InitAWE4 + +InitAWE3: + Mov AX, WC + Call ReadData + Cmp AX, CX + JB InitAWE3 + + Mov SI, Offset InitTable2 + Call InitSetAWE + + Mov SI, Offset InitTable3 + Call InitSetAWE + + Mov AX, HWCF4 + Xor EBX, EBX + Call WriteData + + Mov AX, HWCF5 + Mov EBX, 83h + Call WriteData + + Mov AX, HWCF6 + Mov EBX, 8000h + Call WriteData + + Mov SI, Offset InitTable4 + Call InitSetAWE + + Mov AX, HWCF3 + Mov BX, 4 + Call WriteData + + Ret + +EndP InitAWE + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitDRAMRefresh + + Mov AX, DCYSUSV+1Eh + Mov BX, 80h + Call WriteData + + Mov AX, DCYSUSV+1Fh + Call WriteData + +; + + Mov AX, VTFT+1Eh + Xor EBX, EBX + Call WriteData + + Mov AX, CVCF+1Eh + Call WriteData + + Mov AX, VTFT+1Fh + Call WriteData + + Mov AX, CVCF+1Fh + Call WriteData + +; + + Mov AX, PTRX+1Eh + Call WriteData + + Mov AX, CPF+1Eh + Call WriteData + + Mov AX, PTRX+1Fh + Call WriteData + + Mov AX, CPF+1Fh + Call WriteData + +; + + Mov AX, PSST+1Eh + Call WriteData + Mov AX, PSST+1Fh + Call WriteData + + Mov BX, 0FFFFh + Mov AX, CSL+1Eh + Call WriteData + Mov AX, CSL+1Fh + Call WriteData + + Xor BX, BX + Mov AX, CCCA+1Eh + Call WriteData + Mov AX, CCCA+1Fh + Call WriteData + + Ret + +EndP InitDRAMRefresh + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetDSP Far ; AX = Port + + Push AX + Push CX + Push DX + + Mov DX, AX + Add DL, 6 + Mov AL, 1 + Out DX, AL + + In AL, DX + In AL, DX + In AL, DX + In AL, DX + + Xor AL, AL + Out DX, AL + + Add DL, 8 + Mov CX, 200 + +ResetDSP1: + In AL, DX + Test AL, AL + JS ResetDSP2 + Loop ResetDSP1 + Jmp ResetDSP3 + +ResetDSP2: + Sub DL, 4 + In AL, DX + Cmp AL, 0AAh + JE ResetDSP4 + Add DL, 4 + Loop ResetDSP1 + +ResetDSP3: + StC + +ResetDSP4: + Pop DX + Pop CX + Pop AX + Ret + +EndP ResetDSP + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SBGetRegister + + Out DX, AL + Inc DX + In AL, DX + Dec DX + + Ret + +EndP SBGetRegister + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SBIn ; DX = 2xEh, returns AL + +SBIn1: + In AL, DX + + ShR AL, 7 + LoopZ SBIn + +; Test AL, AL +; JNS SBIn1 + + Add DL, 0Ah-0Eh ; DX = 2xAh -> Data read port + In AL, DX + Add DL, 0Eh-0Ah + + Ret + +EndP SBIn + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far + + Push CS + Pop DS + Assume DS:Driver + + Mov Forced, AL + + Mov DX, BasePort + Cmp DX, 0FFFFh + JE DetectCard1 + + Cmp DX, 620h + JB DetectCard3 + Cmp DX, 680h + JA DetectCard3 + + Call TestAWE + JNC DetectCardFound + Ret + +DetectCard1: + Mov DX, 620h + +DetectCard2: + Call TestAWE + JNC DetectCardFound + + Add DL, 20h + Cmp DL, 80h + JBE DetectCard2 + +DetectCard3: + StC + Ret + +DetectCardFound: + Mov BasePort, DX + + ; Initialise AWE 32 + Call InitAWE + Call InitDRAMRefresh + + ; Detect amount of RAM. + + Mov DX, BasePort + Mov CX, 29 + +DetectCardMemory1: + Mov AX, DCYSUSV + Or AX, CX + Mov BX, 80h + Call WriteData + + Mov AX, VTFT + Or AX, CX + Xor EBX, EBX + Call WriteData + + Mov AX, CVCF + Or AX, CX + Xor EBX, EBX + Call WriteData + + Mov AX, PTRX + Or AX, CX + Mov EBX, 40000000h + Call WriteData + + Mov AX, CPF + Or AX, CX + Mov EBX, 40000000h + Call WriteData + + Mov AX, PSST + Or AX, CX + Xor EBX, EBX + Call WriteData + + Mov AX, CSL + Or AX, CX + Xor EBX, EBX + Call WriteData + + Mov AX, CCCA + Or AX, CX + Mov EBX, 4000000h ; Left read + + Test CL, 2 + JZ DetectCardMemory2 + + Mov EBX, 6000000h ; Left write + +DetectCardMemory2: + Call WriteData + + Dec CX + JNS DetectCardMemory1 + + Xor EDI, EDI ; Amount of memory stored in + ; EDI + + Mov AX, SMALW + Mov EBX, 200000h + Call WriteData + + Mov AX, SMLD + Mov BX, 0FFFFh + Call WriteData + + Mov AX, SMLD + Mov BX, 5555h + Call WriteData + + Mov AX, SMLD + Mov BX, 0AAAAh + Call WriteData + + Mov AX, SMALR + Mov EBX, 200000h + Call WriteData + + Mov AX, SMLD + Call ReadData + + Mov AX, SMLD + Call ReadData + Cmp AX, 0FFFFh + JNE DetectCardMemory6 + + Mov AX, SMLD + Call ReadData + Cmp AX, 5555h + JNE DetectCardMemory6 + + Mov AX, SMLD + Call ReadData + Cmp AX, 0AAAAh + JNE DetectCardMemory6 + + Mov EDI, 20000h + +DetectCardMemory3: ; Set read/write addresses.. + Mov AX, SMALW + Mov EBX, EDI + Add EBX, 200000h + Call WriteData + + Mov AX, SMLD + Mov BX, 5555h + Call WriteData + + Mov AX, SMLD + Mov BX, 0AAAAh + Call WriteData + + Mov AX, SMALR + Mov EBX, 200000h + Call WriteData + + Mov AX, SMLD + Call ReadData + + Mov AX, SMLD + Call ReadData + Cmp AX, 0FFFFh + JNE DetectCardMemory5 + + Mov AX, SMALR + Mov EBX, EDI + Add EBX, 200000h + Call WriteData + + Mov AX, SMLD + Call ReadData + + Mov AX, SMLD + Call ReadData + Cmp AX, 5555h + JNE DetectCardMemory5 + + Mov AX, SMLD + Call ReadData + Cmp AX, 0AAAAh + JNE DetectCardMemory5 + +DetectCardMemory4: + Add EDI, 20000h + Cmp EDI, 0E00000h + JB DetectCardMemory3 + +DetectCardMemory5: + Cmp EDI, 0DFFFE0h + JB DetectCardMemory7 + + Mov EDI, 0DFFFE0h + +DetectCardMemory7: + Test EDI, EDI + JZ DetectCardMemory6 + + Mov AWEMemory, EDI + + Mov MixerPort, 210h + Mov AX, BasePort + Sub AX, 400h + Call ResetDSP + JNC DetectMixer2 + +DetectMixer1: + Mov AX, MixerPort + Call ResetDSP + JNC DetectMixer2 + +DetectMixer3: + Add MixerPort, 10h + Cmp MixerPort, 280h + JBE DetectMixer1 + + Mov DX, BasePort + Sub DX, 400h + Mov MixerPort, DX + + Jmp DetectCard4 + +DetectMixer2: ; OK... DSP found. + ; Get DSP version + Mov DX, AX + Add DL, 0Ch ; 2xCh -> Data ready to send... + + Mov CX, 200 + +DetectMixerLoop1: + In AL, DX +; Test AL, AL +; JS DetectMixerLoop1 + ShR AL, 7 + LoopNZ DetectMixerLoop1 + + Mov AL, 0E1h ; Get DSP version command + Out DX, AL + + Add DL, 0Eh-0Ch ; DX = 2xEh -> Data available status + + Call SBIn + Mov AH, AL ; AH = Major version number + Call SBIn ; AL = Minor version number + + Cmp AX, 40Ch ; SB DSP = 4.12+ + JB DetectMixer3 + + Sub DL, 0Eh + Mov MixerPort, DX + +DetectCard4: + Mov SB16BasePort, DX + Add MixerPort, 4 ; Mixerport + + Add DL, 4 + + Mov AL, 30h + Call SBGetRegister + ShR AL, 3 + Mov VolumeTable, AL + + Mov AL, 31h + Call SBGetRegister + ShR AL, 3 + Mov [VolumeTable+1], AL + + Mov AL, 44h + Call SBGetRegister + ShR AL, 4 + Mov [VolumeTable+2], AL + + Mov AL, 45h + Call SBGetRegister + ShR AL, 4 + Mov [VolumeTable+3], AL + + Mov AL, 46h + Call SBGetRegister + ShR AL, 4 + Mov [VolumeTable+4], AL + + Mov AL, 47h + Call SBGetRegister + ShR AL, 4 + Mov [VolumeTable+5], AL + + Mov DX, MixerPort + Mov AX, 0F834h + Out DX, AX + + Mov AL, 35h + Out DX, AX + + Mov DX, MixerPort + Mov AL, 80h ; IRQ select + Out DX, AL + Inc DL ; 2x5h = Mixer data port + + In AL, DX + + Dec DL + + Mov BX, IRQ + Cmp BX, 0FFFFh + JE DetectCardIRQ1 + Cmp Forced, 0 + JE DetectCardIRQ1 + + Mov AH, 11h + Cmp BL, 2 + JE SetCardIRQ1 + Cmp BL, 9 + JE SetCardIRQ1 + + Mov AH, 12h + Cmp BL, 5 + JE SetCardIRQ1 + + Mov AH, 14h + Cmp BL, 7 + JE SetCardIRQ1 + + Mov AH, 18h + Cmp BL, 10 + JE SetCardIRQ1 + + Jmp NoWindows + +SetCardIRQ1: + Mov AL, 80h + Out DX, AL + Inc DL + Mov AL, AH + Out DX, AL + Dec DL + Jmp DetectCard6 + +DetectCardIRQ1: + Mov BX, 2 + Test AL, 1 + JNZ DetectCardIRQ2 + + Mov BL, 5 + Test AL, 2 + JNZ DetectCardIRQ2 + + Mov BL, 7 + Test AL, 4 + JNZ DetectCardIRQ2 + + Mov BL, 10 + Test AL, 8 + JNZ DetectCardIRQ2 + + StC + Ret + +DetectCardIRQ2: + Cmp IRQ, 0FFFFh + JE DetectCardIRQ3 + + Cmp BX, IRQ + JE DetectCard6 + + StC + Ret + +DetectCardIRQ3: + Mov IRQ, BX + +DetectCard6: + Mov AL, 81h + Out DX, AL + Inc DX + In AL, DX + Dec DX + + And AL, 11 + Xor BX, BX + Cmp AL, 1 + JE DetectCardDMA + + Inc BX + Cmp AL, 2 + JE DetectCardDMA + + Inc BX + Inc BX + Cmp AL, 8 + JNE NoWindows + +DetectCardDMA: + Mov DMA, BX + +DetectCardWindows: + Mov AX, 1600h ; Windows detection. + Int 2Fh + Test AL, 7Fh + JZ NoWindows + + Mov SBIRQMode, 1 + +NoWindows: + Mov EAX, 'Jeff' + ClC + Ret + +DetectCardMemory6: + StC + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetSamplingRate + Assume DS:Driver + + PushA + Push ES + + Mov AX, SB16BasePort + Call ResetDSP + +; Set dma + Mov BX, DMABuffer + Xor AX, AX + Mov DX, DMA + Mov DI, 512 + Call SetDMA + + LES DI, ActualDMAPtr + Xor AX, AX + Mov CX, 256 + Rep StosW + + Mov DX, SB16BasePort + Add DL, 0Ch + +; Mov AL, 0D3h ; Turn off speaker +; Call SBOut + ; Set mixing frequency + Mov AL, 40h + Call SBOut + Mov AL, 0EAh + Call SBOut ; 45454Hz +; Mov AL, 211 +; Call SBOut ; 22222 Hz. + + Mov AL, 0C6h + Call SBOut + Xor AL, AL + Call SBOut + Mov AX, BlockLength + Dec AX + Call SBOut + Mov AL, AH + Call SBOut + + Pop ES + PopA + Ret + +EndP SetSamplingRate + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMIDIIRQ + + PushAD + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Add DI, Offset IRQData + Mov BX, [DI] + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset MIDIIRQHandler + + XChg [ES:BX], EAX + Mov OldIRQHandler, EAX + + Mov AX, IMR + And AX, [DI+2] + + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Pop ES + Pop DS + PopAD + + Ret + +EndP SetMIDIIRQ + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + Assume DS:Driver + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Add DI, Offset IRQData + Mov BX, [DI] + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset SBIRQHandler + + XChg [ES:BX], EAX + Mov OldIRQHandler, EAX + + Mov AX, IMR + And AX, [DI+2] + + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Pop ES + PopAD + + Ret + +EndP SetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIRQ + + PushAD + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Mov BX, [IRQData+DI] + + Mov EAX, OldIRQHandler + Mov [ES:BX], EAX + + Mov AX, IMR + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Pop ES + Pop DS + PopAD + + Ret + +EndP ResetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitMIDI + Assume DS:Driver + + Mov DX, 330h + Call DetectUART + JC DetectMIDI1 + + Mov MIDIPort, 330h + Jmp DetectMIDIEnd + +DetectMIDI1: + Mov DX, 300h + Call DetectUART + JC DetectMIDIEnd + + Mov MIDIPort, 300h + +DetectMIDIEnd: + Ret + +EndP InitMIDI + Assume DS:Nothing + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +FControlWord DW 0 + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + FNInit ; Initialise floating point + FNSTCW FControlWord + And FControlWord, 0F0FFh + FLDCW FControlWord + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + Mov AX, CS + Mov DriverSegment1, AX + Mov DriverSegment2, AX + Mov DriverSegment3, AX + Mov DriverSegment4, AX + Mov DriverSegment5, AX + Mov DriverSegment6, AX + Mov DriverSegment7, AX + Mov DriverSegment8, AX + + In AL, 0A1h + Mov AH, AL + In AL, 21h + Mov IMR, AX + + Cmp SBIRQMode, 0 + JE InitSound1 + + Cmp DMABuffer, 0 + JNE InitSound3 + + Mov AH, 48h + Mov BX, 1024/16 + Int 21h + JNC InitSound4 + + Mov SBIRQMode, 0 + Jmp InitSound1 + +InitSound4: + Mov DMABuffer, AX + +InitSound3: + Call SetIRQ + Call GetTempo + Call SetTempo + Call ResetMemory + Call SetSamplingRate + + Call InitMIDI + + Mov SI, Offset AWE32Msg2 + Mov AX, BasePort + + Mov BX, IRQ + Mov CX, DMA + + Ret + +InitSound1: + Call SetMIDIIRQ + Call GetTempo + Call SetTempo + Call ResetMemory + + Xor AX, AX + Mov ES, AX ; ES = 0 + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset AWEIRQHandler + + ClI + + XChg DWord Ptr [ES:20h], EAX ; Clock tick + Mov OldIRQHandler, EAX + + StI + +InitSound2: + Call InitMIDI + + Mov SI, Offset AWE32Msg + Mov AX, BasePort + + Mov EBX, AWEMemory + SHR EBX, 9 + + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov SI, Offset AWE32ReinitMsg + Mov BX, 40 + Call SetInfoLine + + Call ResetUART + Call InitAWE + Call InitDRAMRefresh + + Cmp SBIRQMode, 0 + JE ReInitSound1 + + Call ResetIRQ + Call SetIRQ + Call SetSamplingRate + Call ReinitUART + Ret + +ReInitSound1: + Xor AX, AX + Mov ES, AX ; ES = 0 + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset AWEIRQHandler + + Mov DWord Ptr [ES:20h], EAX ; Clock tick + + Call ResetIRQ + Call SetMIDIIRQ + Call ReinitUART + + Ret + +EndP ReInitSound + Assume DS:Nothing + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + + Call GotoHomeDirectory + + ; Now to save config into driver file. + Push CS + Pop DS + Assume DS:Driver + + Mov AX, 3D02h ; Read write access + Mov DX, Offset DriverName + Int 21h + JC SaveConfig2 + + Mov BX, AX + + Mov AX, 4200h + Xor CX, CX + Mov DX, Offset CONFIGURATIONOFFSET + Int 21h + JC SaveConfig1 + + Mov AH, 40h + Mov CX, CONFIGSIZE + Mov DX, Offset Chorus + Int 21h + +SaveConfig1: + PushF + Mov AH, 3Eh + Int 21h + PopF + +SaveConfig2: + Call ResetIRQ + + Cmp SBIRQMode, 0 + JE UnInitSound1 + + Mov DX, SB16BasePort + Add DL, 0Ch + + Call ResetUART + + Mov AX, SB16BasePort + Call ResetDSP + + Call InitAWE + + Push ES + Mov AH, 49h + Mov ES, DMABuffer + Int 21h + Pop ES + + Ret + +UnInitSound1: + Mov AL, 34h + Out 43h, AL + + Xor AX, AX + Out 40h, AL + Out 40h, AL + + Mov ES, AX + Mov EAX, OldIRQHandler + Mov [ES:20h], EAX + + Mov AX, SB16BasePort + Call ResetDSP + Call ResetUART + Call InitAWE + Call ResetIRQ + Ret + +EndP UnInitSound + Assume DS:Nothing + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + Push CS + Pop DS + Assume DS:Driver + +Poll1: + Call [UARTBufferEmpty] + JNC PollEnd + + Xor BX, BX + + ClI + + Mov BL, MIDIBufferHead + Cmp BL, MIDIBufferTail + JZ PollEnd ; Nothing in queue + + Inc BL + Mov AL, [MIDIBuffer+BX] + Mov MIDIBufferHead, BL + + Call [UARTSend] + Jmp Poll1 + +PollEnd: + StI + Ret + +EndP Poll + Assume DS:Nothing + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Push AX + Push BX + Push DX + + Cmp CS:SBIRQMode, 0 + JE SetTempo1 + ; BlockLength = 55555/BPM + ; BlockLength = 45454*5/2 + ; = 113635 + Mov AX, 48099 + Mov DX, 1 + + Div BX + Dec AX + Dec AX + Mov CS:BlockLength, AX + +; Mov DX, SB16BasePort +; Add DL, 0Ch + + Jmp SetTempo2 + +SetTempo1: + ; Frames per second = 2 * (0.4*Tempo) + Mov AX, 0C214h + Mov DX, 16h ; Ticks = (1193181/(2*0.4))/Tempo + Div BX + + ; AX contains counter. + Mov CS:AWEUpdateTimer, AX + + Out 40h, AL ; Timer IRQ. + Mov AL, AH + Out 40h, AL + +SetTempo2: + Pop DX + Pop BX + Pop AX + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + Ret + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Mov CS:Stereo, AL + + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc LoadSample Far + ; if no sample, then do nothing + ; MemoryUsed = length of sample + ; if sustain loop, then use sustain + ; loop information + ; if no sustain loop, then use loop + ; information + ; if no loop or sustain loop, + ; memoryused += 16; (16 zero samples + ; at the end) + ; + PushAD + Push DS + Push ES + Push FS + + Push AX + + ClI + + Call EnableRAM ; Enable access to DRAM. + + ; Set destination address + Mov AX, SMALW + Mov EBX, CS:AWEMemoryUsed + Add EBX, 200000h + Call WriteData + + Mov DX, CS:BasePort + Add DX, 802h ; Index + Mov AX, 32+26 + Out DX, AX + + Pop AX + + Mov FS, CS:SongDataArea + LEA DI, [EAX*4+EAX] + ShL DI, 2 + Add DI, Offset AWEDataTable-20 + + Mov ECX, -1 + + Mov DWord Ptr [CS:DI], ECX ; Start + Mov DWord Ptr [CS:DI+4], ECX ; Loop start + Mov DWord Ptr [CS:DI+8], ECX ; Loop end + Mov DWord Ptr [CS:DI+12], ECX ; Size occupied + Mov DWord Ptr [CS:DI+16], ECX ; Size occupied + + Mov BP, AX + Add BP, BP + Mov BP, [FS:64910+BP] + + Xor CX, CX ; From the start of the sample.. + Call GetSampleLocation ; Returns DS:ESI, ECX = length + JC LoadSampleNoError + + JZ LoadSample1 + + ; 16 bit + + Mov CS:LoadSampleFuncF, Offset Load16BitSamplesForwards + Mov CS:LoadSampleFuncB, Offset Load16BitSamplesBackwards + + Jmp LoadSample2 + +LoadSample1: ; 8 bit + Mov CS:LoadSampleFuncF, Offset Load8BitSamplesForwards + Mov CS:LoadSampleFuncB, Offset Load8BitSamplesBackwards + +LoadSample2: + Mov AL, [FS:BP+12h] + Test AL, 30h ; Loop or sustain loop? + JZ LoadSampleNoLoop + + Mov EBX, [FS:BP+34h] ; Loop begin + Mov EDX, [FS:BP+38h] ; Loop end + Test AL, 20h ; Sustain loop? + JZ LoadSample3 + + ShR AL, 1 + Mov EBX, [FS:BP+40h] + Mov EDX, [FS:BP+44h] + Jmp LoadSample3 + +LoadSampleError: + ClC + Jmp LoadSampleEnd + +LoadSampleNoError: + StC + +LoadSampleEnd: + StI + Pop FS + Pop ES + Pop DS + PopAD + + Ret + +LoadSampleNoLoop: ; ECX contains length of sample + Mov EAX, ECX + Mov EDX, AWEMemoryUsed + Mov EBX, AWEMemory + Sub EBX, EDX ; EBX = AWEMemory remaining + + Mov CL, Compress + ShR EAX, CL ; Compress sample + Add EAX, 16 ; zeroes at end of sample + + Cmp EAX, EBX + JA LoadSampleError + + Mov ECX, EAX + Add AWEMemoryUsed, EAX ; Record memory as used + Mov [CS:DI+12], EAX + + Add EDX, 200000h + + Sub ECX, 16 ; Number of samples to transfer + Mov [CS:DI], EDX + Add EDX, ECX + Mov [CS:DI+4], EDX ; Loop start + Add EDX, 14 + Mov [CS:DI+8], EDX ; Loop end + + ; Now to transfer samples to AWE32 + Call [CS:LoadSampleFuncF] + ; Now to shove a whole lot of zeroes + Xor AX, AX + Mov CX, 16 + +LoadSampleNoLoop2: + Out DX, AX + Loop LoadsampleNoLoop2 + + Jmp LoadSampleNoError + +LoadSample3: ; OK... EBX = loop start + ; EDX = loop end + ; AL&40h = ping pong + Test AL, 40h + JNZ LoadSamplePingPong + + Mov CL, Compress + + Push EBX + + ShR EDX, CL + ShR EBX, CL + Mov EAX, EDX + Add EAX, 2 ; For loop fixing + + Mov ECX, AWEMemory + Sub ECX, AWEMemoryUsed ; ECX = AWEMemoryRemaining + + Cmp EAX, ECX + Pop ECX + JA LoadSampleError ; Sufficient memory? + Push ECX + + Mov ECX, EAX + Mov EAX, AWEMemoryUsed + Add AWEMemoryUsed, ECX + Mov [CS:DI+12], ECX + + Sub ECX, 2 + + Add EAX, 200000h + Mov [CS:DI], EAX + + Add EDX, EAX + Add EAX, EBX + + Mov [CS:DI+4], EAX + Mov [CS:DI+8], EDX + + Call [CS:LoadSampleFuncF] + ; Now to fix loop.. 1 extra + ; sample. + + Pop ESI ; Loop start + Test Byte Ptr [FS:BP+12h], 2 + JZ LoadSampleForwards1 + + Add ESI, ESI + +LoadSampleForwards1: + Int 3 + + Mov ECX, 2 + Call [CS:LoadSampleFuncF] + + Jmp LoadSampleNoError + +LoadSamplePingPong: + Mov CL, Compress + ShR EDX, CL + ShR EBX, CL + + Mov EAX, EDX + Add EAX, EDX + Sub EAX, EBX + Inc EAX + + Mov ECX, AWEMemory + Sub ECX, AWEMemoryUsed + + Cmp EAX, ECX + JA LoadSampleError + + Mov [CS:DI+12], EAX + Mov ECX, AWEMemoryUsed + Add AWEMemoryUsed, EAX + + Add ECX, 200000h + Add EAX, ECX + Dec EAX + + Mov [CS:DI], ECX + Add ECX, EBX + Mov [CS:DI+4], ECX + Mov [CS:DI+8], EAX + + Mov EAX, [CS:DI] + Add EAX, EDX + Mov [CS:DI+16], EAX + + Mov ECX, EDX + Sub EDX, EBX + Push EDX + + Call [CS:LoadSampleFuncF] + + Pop ECX + Inc ECX + + Call [CS:LoadSampleFuncB] + + Jmp LoadSampleNoError + +EndP LoadSample + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + PushAD + + LEA DI, [EAX*4+EAX] ; DI = AX * 5 + ShL DI, 2 + Add DI, Offset AWEDataTable + + Mov EBX, [CS:DI+12] + Mov EAX, CS:AWEMemoryUsed + Sub EAX, EBX + Add EAX, 200000h + Cmp EAX, [CS:DI] + JNE ReleaseSample1 + + Sub AWEMemoryUsed, EBX +ReleaseSample1: + Mov EAX, -1 + Mov [CS:DI], EAX + Mov [CS:DI+4], EAX + Mov [CS:DI+8], EAX + Mov [CS:DI+12], EAX + + PopAD + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Push CS + Pop ES + + Xor EAX, EAX + Mov CS:AWEMemoryUsed, EAX + + Mov DI, Offset AWEDataTable + Mov CX, 1000 + Mov AX, 0FFFFh + Rep StosW + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + Push CS + Pop DS + Assume DS:Driver + + Mov SI, Offset AWE32Status + + Mov EAX, AWEMemory + Sub EAX, AWEMemoryUsed + SHR EAX, 9 + + ClC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset GUSScreenList + + ClC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far ; Returns AX, given DI + + Xor AH, AH + Mov AL, [CS:VolumeTable+DI] + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far ; Given AX, DI + + Push DS + Push DX + + Push CS + Pop DS + Assume DS:Driver + + Mov [VolumeTable+DI], AL + + Mov DX, MixerPort + Mov AL, 30h + Mov AH, [VolumeTable] + ShL AH, 3 + Out DX, AX + + Mov AL, 31h + Mov AH, [VolumeTable+1] + ShL AH, 3 + Out DX, AX + + Mov AL, 44h + Mov AH, [VolumeTable+2] + ShL AH, 4 + Out DX, AX + + Mov AL, 45h + Mov AH, [VolumeTable+3] + ShL AH, 4 + Out DX, AX + + Mov AL, 46h + Mov AH, [VolumeTable+4] + ShL AH, 4 + Out DX, AX + + Mov AL, 47h + Mov AH, [VolumeTable+5] + ShL AH, 4 + Out DX, AX + + Pop DX + Pop DS + Ret + +EndP SetVariable + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 30 ; Maximum number of channels the + ; driver can handle. +StopAfterPlay DW 0 +DefaultChannels DW 30 +DriverFlags DW 1 ; MIDI Out supported + + DW 4 Dup (0) + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + + DW Offset SendUARTOut ; For MIDI Out + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/BASE1.ASM b/SoundDrivers/BASE1.ASM new file mode 100755 index 0000000..01ff0a5 --- /dev/null +++ b/SoundDrivers/BASE1.ASM @@ -0,0 +1,2070 @@ +; +; Analog Device's AD1816 +; + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;********************************** + +PNPSERIALID EQU 0FFFFFFFFh +PNPVENDORID EQU 1114B250h + +STEREOENABLED EQU 1 +DMABUFFERLENGTH EQU 4096 +MIXRESOLUTION EQU 32 ; 32 bit mixing for +MIXTABLESIZE EQU 2*256*65 + +DMASize DW DMABUFFERLENGTH/2 + +ESSMsg DB "SoundSystem Base 1 found", 13 + DB "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, DMA ", 0FDh, "D", 0 + +ESSNoMemoryMsg DB "SoundSystem Base 1 found", 13 + DB "Error: Insufficient memory", 0 + +ReinitMsg DB "SoundSystem Base 1 reinitialised", 0 + +DriverName DB "ITBASE1.DRV", 0 + +Forced DB 0 +Stereo DB 0 +MixVolume DW 0 + +BytesToMix DW 1000 +ESSMixConst DB 0 + +MixSegment DW 0 +DMASegment DW 0 + +MixTransferOffset DW 0 +MixTransferRemaining DW 0 + +CONFIGURATIONOFFSET EQU $+128 +CONFIGSIZE EQU 6 +MixMode DW 0 +MixModeOffset DW 0 +Filter DW 0 + +IMR DW 0 +OldESSIRQHandler DD 0 + +MIDIIRQ DW 0 +MIDIPort DW 0 + +FilterValue DD 0 +FilterValue2 DD 0 + +IRQData Label Word + DW 20h, 1111111111111110b ; IRQ 0 + DW 24h, 1111111111111101b ; IRQ 1 + DW 28h, 1111110111111011b ; IRQ 2 + DW 2Ch, 1111111111110111b ; IRQ 3 + DW 30h, 1111111111101111b ; IRQ 4 + DW 34h, 1111111111011111b ; IRQ 5 + DW 38h, 1111111110111111b ; IRQ 6 + DW 3Ch, 1111111101111111b ; IRQ 7 + DW 1C0h, 1111111011111011b ; IRQ 8 + DW 1C4h, 1111110111111011b ; IRQ 9 + DW 1C8h, 1111101111111011b ; IRQ 10 + DW 1CCh, 1111011111111011b ; IRQ 11 + DW 1D0h, 1110111111111011b ; IRQ 12 + DW 1D4h, 1101111111111011b ; IRQ 13 + DW 1D8h, 1011111111111011b ; IRQ 14 + DW 1DCh, 0111111111111011b ; IRQ 15 + +ESSScreenList Label + DW 16 + DW Near Ptr IdleFunctionList + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr ESSHeaderLine + + DW Near Ptr DriverText + + DW Near Ptr MixModeText + DW Near Ptr MixModeButton1 ; 6 + DW Near Ptr MixModeButton2 ; + DW Near Ptr MixModeButton3 ; 8 + DW Near Ptr MixModeButton4 ; 9 + + DW Near Ptr FilterText + DW Near Ptr FilterButton1 ; 11 + DW Near Ptr FilterButton2 + DW Near Ptr FilterButton3 + + DW Near Ptr VolumeText + DW Near Ptr VolumeBox1 + + DW Near Ptr MasterVolumeLeft ; 16 + DW Near Ptr MasterVolumeRight ; 17 + DW Near Ptr PhatStereo ; 18 + + DW 0 + +ESSHeaderLine DW 10 + DB "SoundSystem Base 1 Driver", 0 + +EmptyObject DW 1 + DB 0, 0 + DB 0 + DB 0 + +DriverText DW 1 + DB 29, 48 + DB 21h + DB "SoundSystem Base 1 Driver 1.0 for Impulse Tracker", 0 + +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +IdleFunctionList DD 0 + DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +VolumeText DW 1 + DB 2, 14 + DB 20h + DB "Master Volume Left", 13 + DB "Master Volume Right", 13 + DB "3D Phat Stereo", 13 + DB 0 + +VolumeBox1 DW 0 + DB 21, 13, 39, 17 + DB 25 + +PhatStereo DW 14 + DB 22, 16 + DW 0, 15 + DW 9, 2 + DW 17, 6, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 16 + +MasterVolumeLeft DW 14 + DB 22, 14 + DW 0, 63 + DW 9, 0 + DW 0FFFFh, 17, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 16 + +MasterVolumeRight DW 14 + DB 22, 15 + DW 0, 63 + DW 9, 1 + DW 16, 18, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 16 + +MixModeText DW 1 + DB 2, 18 + DB 20h + DB "Mixing Mode, Playback Frequency: ", 0FDh, "DHz", 0 +MixSpeed DW 44100 + +MixModeButton1 DW 2 + DW 18, 7, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment1 DW 0 + DW 0 + DW Offset SetMixMode +DriverSegment2 DW 0 + DB 3, 20, 32, 22, 8 + DB 0 + DB " 16 Bit, Non-Interpolated", 0 + +MixModeButton2 DW 2 + DW 6, 8, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment3 DW 0 + DW 2 + DW Offset SetMixMode +DriverSegment4 DW 0 + DB 3, 23, 32, 25, 8 + DB 0 + DB " 16 Bit, Interpolated", 0 + +MixModeButton3 DW 2 + DW 7, 9, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment5 DW 0 + DW 4 + DW Offset SetMixMode +DriverSegment6 DW 0 + DB 3, 26, 32, 28, 8 + DB 0 + DB " 32 Bit, Non-Interpolated", 0 + +MixModeButton4 DW 2 + DW 8, 11, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment7 DW 0 + DW 6 + DW Offset SetMixMode +DriverSegment8 DW 0 + DB 3, 29, 32, 31, 8 + DB 0 + DB " 32 Bit, Interpolated", 0 + +FilterText DW 1 + DB 2, 33 + DB 20h + DB "Filter mode", 0 + +FilterButton1 DW 2 + DW 9, 12, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment9 DW 0 + DW 0 + DW Offset SetFilter +DriverSegment10 DW 0 + DB 3, 35, 29, 37, 8 + DB 0 + DB " No Filter", 0 + +FilterButton2 DW 2 + DW 11, 13, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment11 DW 0 + DW 1 + DW Offset SetFilter +DriverSegment12 DW 0 + DB 3, 38, 29, 40, 8 + DB 0 + DB " 50% Filter", 0 + +FilterButton3 DW 2 + DW 12, 0FFFFh, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment13 DW 0 + DW 2 + DW Offset SetFilter +DriverSegment14 DW 0 + DB 3, 41, 29, 43, 8 + DB 0 + DB " 75% Filter", 0 + +VolumeTable DB 56, 56, 0 + +; ÄÄ MixingRoutines ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixBufferPos DW 0 + +include dmasirq.inc +include mix.inc +include m12bit.mix +include m12biti.mix +include m32bit.mix +include m32biti.mix + +MixFunctionTables Label + +include m12bit.inc ; contains the tables +include m12biti.inc +include m32bit.inc +include m32biti.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +RelocationTable Label Word + DW Offset DriverSegment1, Offset DriverSegment2 + DW Offset DriverSegment3, Offset DriverSegment4 + DW Offset DriverSegment5, Offset DriverSegment6 + DW Offset DriverSegment7, Offset DriverSegment8 + DW Offset DriverSegment9, Offset DriverSegment10 + DW Offset DriverSegment11, Offset DriverSegment12 + DW Offset DriverSegment13, Offset DriverSegment14 + DW 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc AD1816Wait + + PushA + Xor CX, CX + Mov DX, CS:BasePort + +AD1816Wait1: + In AL, DX + Test AL, 80h + LoopZ AD1816Wait1 + + PopA + Ret + +EndP AD1816Wait + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc AD1816RegisterOut ; AL = indirect register, BX = contents + + Call AD1816Wait + + Push DX + PushF + + ClI + + Mov DX, CS:BasePort + Out DX, AL + Add DL, 2 + + Mov AL, BL + Out DX, AL + Inc DX + Mov AL, BH + Out DX, AL + + PopF + Pop DX + + Ret + +EndP AD1816RegisterOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc AD1816RegisterIn ; AL = register + ; Returns BX + + Call AD1816Wait + + Push AX + Push DX + + Mov DX, CS:BasePort + Out DX, AL + Add DL, 2 + + In AL, DX + Mov BL, AL + Inc DX + In AL, DX + Mov BH, AL + + Pop DX + Pop AX + + Ret + +EndP AD1816RegisterIn + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixMode Far + + Push CS + Pop ES + Mov DI, Offset MixMode + + Ret + +EndP GetMixMode + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetFilter Far + + Push CS + Pop ES + Mov DI, Offset Filter + + Ret + +EndP GetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetFilter Far + + Mov AX, [SI+22] + Mov CS:FilterValue, 0 + Mov CS:Filter, AX + + Mov AX, 1 + Ret + +EndP SetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixMode Far + + Mov AX, [SI+22] + + ClI + + Mov CS:MixMode, AX + + Mov BX, 180 + Mul BX + Mov CS:MixModeOffset, AX + + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS:RecalculateAllVolumes + + StI + + Mov AX, 1 + Ret + +EndP SetMixMode + Assume DS:Nothing + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +PnP_SerialID DD 0 +PnP_VendorID DD 0 +PnP_ReadPort DW 0 +PnP_CSN DB 0 +PnP_CardFound DB 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_Delay + Assume DS:Driver + + Push AX CX + + Mov CX, 180h +PnP_Delay1: + In AL, 21h + Loop PnP_Delay1 + + Pop CX AX + Ret + +EndP PnP_Delay + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_WriteData + + Mov DX, 279h + Out DX, AL + + Mov AL, AH + Mov DH, 0Ah + Out DX, AL + Ret + +EndP PnP_WriteData + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_ReadData + + Mov DX, 279h + Out DX, AL + + Mov DX, PnP_ReadPort + In AL, DX + + Ret + +EndP PnP_ReadData + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_Isolate + + Mov AX, 402h + Call Pnp_WriteData ; Reset CSNs + +PnP_IsolateNextCard: + Mov AX, 0003h + Call PnP_WriteData ; Wake[0] + + Mov AX, PnP_ReadPort + ShL AX, 6 + Xor AL, AL + Call PnP_WriteData ; Set Read Data port. + + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + + Mov AL, 1 ; Serial Isolation + Mov DX, 279h + Out DX, AL + + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + + Mov BL, 6Ah + Mov CX, 64 + Mov DX, PnP_ReadPort + + ClI + +PnP_Isolate1: + ShR PnP_SerialID, 1 + RCR PnP_VendorID, 1 + + Mov BH, BL + ShR BH, 1 + Xor BH, BL + ShR BX, 1 + + In AL, DX + Mov AH, AL + Call PnP_Delay + In AL, DX + Call PnP_Delay + + Cmp AX, 55AAh + JNE PnP_Isolate2 + + Xor BL, 80h + Or PnP_SerialID, 80000000h + +PnP_Isolate2: + Dec CX + JNZ PnP_Isolate1 + + Mov CX, 8 + Xor BH, BH + +PnP_Isolate3: + ShR BH, 1 + + In AL, DX + Mov AH, AL + Call PnP_Delay + In AL, DX + Call PnP_Delay + Cmp AX, 55AAh + JNE PnP_Isolate4 + + Or BH, 80h + +PnP_Isolate4: + Dec CX + JNZ PnP_Isolate3 + + StI + + Cmp BL, BH ; Matching Checksum? + JNE PnP_IsolateFinished + + ; assign CSN + Inc PnP_CSN + + Mov AL, 6 + MOv AH, PnP_CSN + Call PnP_WriteData + + Cmp PnP_VendorID, PNPVENDORID + JNE PnP_IsolateNextCard + Cmp PnP_SerialID, PNPSERIALID + JNE PnP_IsolateNextCard + + Mov AL, 3 + Call PnP_WriteData + Mov AX, 007h + Call PnP_WriteData + + Mov AL, 64h + Call PnP_ReadData + Mov AH, AL + Mov AL, 65h + Call PnP_ReadData ; AX = address. + Cmp BasePort, 0FFFFh + JE PnPBasePortOK + + Cmp BasePort, AX + JNE PnP_IsolateNextCard + +PnPBasePortOK: + Mov BasePort, AX + + Mov AL, 70h + Call PnP_ReadData ; AL[3:0] = IRQ + And AX, 15 + JZ PnP_IsolateNextCard + Mov IRQ, AX + + Mov AL, 74h + Call PnP_ReadData ; AL[2:0] = DMA + And AX, 7 + Cmp AL, 4 + JE PnP_IsolateNextCard + Mov DMA, AX + + Mov AX, 107h ; LDN 1 - MIDI device + Call PnP_WriteData + + Mov AL, 60h + Call PnP_ReadData + Mov AH, AL + Mov AL, 61h + Call PnP_ReadData ; AX = address. + Mov MIDIPort, AX + + Mov AL, 70h + Call PnP_ReadData ; AL[3:0] = IRQ + And AX, 15 + Mov MIDIIRQ, AX + + Mov Pnp_CardFound, 1 + Jmp PnP_IsolateNextCard + +PnP_IsolateFinished: + Mov AL, PnP_CSN + ShL AL, 1 + Or AL, PnP_CardFound + + Ret + +EndP PnP_Isolate + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far ; returns carry clear if succesful + + Push CS + Pop DS + + Xor AL, AL + Mov DX, 279h + Out DX, AL + Out DX, AL + + Mov AL, 6Ah ; Starting value + Mov CX, 32 + +PnP_InitiationKeyLoop: + Out DX, AL + + Mov AH, AL + ShR AH, 1 + Xor AH, AL + ShR AX, 1 + + Dec CX + JNZ PnP_InitiationKeyLoop + +; Try three ports before concluding no PnP cards: 20Fh, 27Bh, 213h + +PnP_DetectCardPort1: + Mov PnP_ReadPort, 20Fh + Call PnP_Isolate + JZ PnP_DetectCardPort2 + Test AL, 1 + JZ PnP_DetectCardNotFound + Jmp PnP_DetectCardFound + +PnP_DetectCardPort2: + Mov PnP_ReadPort, 27Bh + Call PnP_Isolate + JZ PnP_DetectCardPort3 + Test AL, 1 + JZ PnP_DetectCardNotFound + Jmp PnP_DetectCardFound + +PnP_DetectCardPort3: + Mov PnP_ReadPort, 213h + Call PnP_Isolate + Test AL, 1 + JNZ PnP_DetectCardFound + +PnP_DetectCardNotFound: + StC + Jmp PnP_DetectEnd + +PnP_DetectCardFound: + ClC + +PnP_DetectEnd: ; Return PnP to wait for key state + Mov AX, 202h + Call PnP_WriteData + Mov EAX, 'Jeff' + + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixModeTable Label Word + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + +Proc MixSamples ; Given DS:SI = info tables, CX = numchannels + + ; 1. Clean buffer + ; + update variables + ; 2. Update parameters + ; 3. Mix func + ; 4. Return + + Push CX + + Mov CX, BytesToMix + Mov ES, MixSegment + Mov DI, MIXTABLESIZE + Xor EAX, EAX + Mov DX, CX + Add CX, CX + + Mov MixTransferOffset, DI ; } Memory write + + Cmp Stereo, 0 + JE MixSamples1 + + Mov DX, CX + +MixSamples1: + Rep StosD ; } Memory write + Mov MixTransferRemaining, DX ; } + + Pop CX + +MixSamples2: + Test Byte Ptr [SI], 1 + JZ MixSamplesEnd2 + Cmp Byte Ptr [SI+36h], 100 + JE MixSamplesEnd2 + + Push CX + Mov CX, [SI] + + Test CH, 2 + JZ MixSamples3 + And Byte Ptr [SI], Not 1 + + Jmp MixSamplesEnd +; Cmp MixMode, 8 ; Is it volume ramping? +; JB MixSamplesEnd + +MixSamples3: + Test CL, 20h ; New freq? + JZ MixSamples5 + + Mov AX, [SI+10h] + Mov DX, [SI+12h] + Mov BX, MixSpeed + Cmp DX, BX + JAE MixSamplesHandleError + + Div BX + ShL EAX, 16 + Xor AX, AX + Div BX + Mov STEPVALUE, EAX + +MixSamples4: + Test CH, 1 + JZ MixSamples5 + + Mov DWord Ptr [SI+1Ch], 0 ; Current Volume = 0 + ; for volume sliding. +MixSamples5: + Test CX, 8440h ; New volume or panning? + JZ MixSamplesMix + + Xor AX, AX + Test CH, 8 ; Muted? + JNZ MixModeCommon + + Mov BX, MixMode + Add BL, Stereo + Add BX, BX + Jmp [CS:MixModeTable+BX] + +Mix0Mode: ; 16-bit mixing, no interpolation +Mix0ModeMono: ; and 16-bit mixing, interpolation + Mov AL, [SI+20h] + ShR AL, 1 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 30 ; Use left only-mixing for mono + Jmp MixModeCommon + +Mix0ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix0ModeSurround + + Mul Byte Ptr [SI+20h] ; Final volume + Add AX, 64 + ShR AX, 7 + Mov [SI+0Ch], AX ; Store into right volume + + Mov AL, 64 + Sub AL, [SI+37h] + Mul Byte Ptr [SI+20h] + Add AX, 64 + ShR AX, 7 + Mov [SI+0Eh], AX ; Left volume + + Mov CH, AL ; CH = left volume + Mov CL, [SI+0Ch] ; CL = right volume + Mov AX, 0 + + Test CX, CX + JZ MixModeCommon + + Mov AL, 30 ; Left only... + Test CL, CL + JZ MixModeCommon + + Mov AL, 60 + Test CH, CH + JZ MixModeCommon + + Mov AL, 90 + Cmp CL, CH + JZ MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix0ModeSurround: + Mov AL, [SI+20h] + ShR AL, 2 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 150 ; Surround + Jmp MixModeCommon + +Mix6ModeMono: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 8 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Test AX, AX + JZ MixModeCommon + Mov AX, 30 + Jmp MixModeCommon + +Mix6ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix6ModeSurround + + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Ch], AX ; Store into right volume + Mov BX, AX + ShL EAX, 16 + + Mov AL, 64 ; Do left volume + Sub AL, [SI+37h] ; AL = 64-FinalPan + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Eh], AX + + Mov ECX, EAX + + ; BX = right volume + ; CX = Left volume + Mov AX, 0 + Test ECX, ECX + JZ MixModeCommon + + Mov AL, 30 + Test BX, BX + JZ MixModeCommon + + Mov AL, 60 + Test CX, CX + JZ MixModeCommon + + Mov AL, 90 + Cmp CX, BX + JE MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix6ModeSurround: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 9 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + JZ MixModeCommon + Mov AX, 150 + Jmp MixModeCommon + +MixModeCommon: ; Requires AX = 30/60/90 etc. depending + ; On mixing mode type. + ; This will add 180 for 16-bit, + ; And sort out loop types. + Mov BL, [SI+0Ah] + Test Byte Ptr [SI+18h], 2 ; 16 bit? + JZ MixModeCommon1 + + Add AX, 180 + +MixModeCommon1: + Cmp BL, 8 + JB MixModeCommon3 ; No loop + JE MixModeCommon2 ; Forwards loop + + Add AX, 10 + +MixModeCommon2: + Add AX, 10 + +MixModeCommon3: + Add AX, Offset MixFunctionTables + Add AX, MixModeOffset + Mov [SI+8], AX ; Offset... + +MixSamplesMix: + Mov BX, [SI+8] ; BX = offset into + Mov EAX, [CS:BX+2] + Mov DWord Ptr PreMixFunction, EAX + Mov EAX, [CS:BX+6] + Mov DWord Ptr MixFunctionSeparateBackwards, EAX + + Mov AX, BytesToMix + Mov MixBlockSize, AX + Mov MixBufferOffset, MIXTABLESIZE + + Mov EAX, CURRENTPOSITION + Mov OLDPOSITION, EAX + + Call Word Ptr [CS:BX] + + And Word Ptr [SI], 0111100010001101b + Jmp MixSamplesEnd + +MixSamplesHandleError: + Mov Word Ptr [SI], 200h + + Test Byte Ptr [SI+3Ah], 80h + JNZ MixSamplesEnd + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Turn off channel + +MixSamplesEnd: + Pop CX + +MixSamplesEnd2: + Add SI, 128 + Dec CX + JNZ MixSamples2 + + Ret + +EndP MixSamples + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ESSIRQHandler + + PushAD + Push DS + Push ES + + ClD + + Mov AX, CS + Mov DS, AX + Assume DS:Driver + + Mov DX, [BasePort] + + Inc DX + In AL, DX + Mov AH, AL + Xor AL, AL + Out DX, AL + + Mov AL, 20h + Cmp IRQ, 8 + JB WSSAckIRQ1 + + Out 0A0h, AL + +WSSAckIRQ1: + Out 20h, AL + +DMAPort1 EQU $+1 + In AL, 1 + Mov BL, AL +DMAPort2 EQU $+1 + In AL, 1 + Mov BH, AL + + Xor AX, AX + + Cmp BX, DMABUFFERLENGTH/2 + JB WSSIRQHandler1 + + Mov AX, DMABUFFERLENGTH/2 + +WSSIRQHandler1: + CLD + + + ; OK... time to get next block + ; Check whether stereo thing is on.. + ; + LES DI, [ActualDMAPtr] + Add DI, AX + + Mov BX, DMASize ; BX = bytes required + ShR BX, 1 + ; BX = samples required + Mov BP, 8 ; Skip for mono + Mov CL, 14 ; Shift for mono + + Cmp Stereo, 0 + JE ESSIRQHandlerMono + + Mov BP, 4 ; Stereo skip value. + Dec CL + +ESSIRQHandlerMono: + Call SaveEMSPageFrame + + Cmp MixTransferRemaining, 0 + JNE ESSIRQHandler4 + Assume DS:Nothing + +ESSIRQHandler3: + Push BX + Push CX + Push BP + Push ES + Push DI + + Call Update + Call MixSamples + + Pop DI + Pop ES + Pop BP + Pop CX + Pop BX + +ESSIRQHandler4: + Mov DS, MixSegment + Mov SI, MixTransferOffset + Mov DX, BX ; DX = samples to transfer + Cmp DX, MixTransferRemaining + JBE ESSIRQHandler5 + + Mov DX, MixTransferRemaining + +ESSIRQHandler5: + Push DX + Cmp CS:Filter, 1 + JB ESSIRQHandler6 + JE ESSIRQHFilter + + Cmp CS:Stereo, 0 + JE ESSIRQ3QFilterMono + +ESSIRQ3QFilterStereo: + Push BX + + Mov EBX, FilterValue + Mov EBP, FilterValue2 + ShR DX, 1 + +ESSIRQ3QFilterStereo1: + Mov EAX, EBX + Mov ECX, EBP + Add EAX, [SI] + Add ECX, [SI+4] + SAR EAX, 1 + SAR ECX, 1 + Add EBX, EAX + Add EBP, ECX + SAR EBX, 1 + SAR EBP, 1 + + Mov EAX, EBX + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSS3QFilterStereoClip1 + Cmp EAX, 7FFFh + JG WSS3QFilterStereoClip2 + +ESSIRQ3QFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSS3QFilterStereoClip3 + Cmp EAX, 7FFFh + JG WSS3QFilterStereoClip4 + +ESSIRQ3QFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ ESSIRQ3QFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp WSSMixTransferEnd + +ESSIRQ3QFilterMono: + Push BX + + Mov EBX, FilterValue + +ESSIRQ3QFilterMono1: + Mov EAX, EBX + Add EAX, [SI] + SAR EAX, 1 + Add EBX, EAX + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL WSS3QFilterMonoClip1 + Cmp EAX, 7FFFh + JG WSS3QFilterMonoClip2 + +ESSIRQ3QFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ ESSIRQ3QFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp WSSMixTransferEnd + +ESSIRQHFilter: + Cmp CS:Stereo, 0 + JE ESSIRQHFilterMono + +ESSIRQHFilterStereo: + Push BX + + Mov EBX, FilterValue + Mov EBP, FilterValue2 + ShR DX, 1 + +ESSIRQHFilterStereo1: + Add EBX, [SI] + Add EBP, [SI+4] + + SAR EBX, 1 + SAR EBP, 1 + + Mov EAX, EBX + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSSHFilterStereoClip1 + Cmp EAX, 7FFFh + JG WSSHFilterStereoClip2 + +ESSIRQHFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSSHFilterStereoClip3 + Cmp EAX, 7FFFh + JG WSSHFilterStereoClip4 + +ESSIRQHFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ ESSIRQHFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp WSSMixTransferEnd + +ESSIRQHFilterMono: + Push BX + + Mov EBX, FilterValue + +ESSIRQHFilterMono1: + Add EBX, [SI] + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL WSSHFilterMonoClip1 + Cmp EAX, 7FFFh + JG WSSHFilterMonoClip2 + +ESSIRQHFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ ESSIRQHFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp WSSMixTransferEnd + +ESSIRQHandler6: + Mov EAX, [SI] + SAR EAX, CL + + Cmp EAX, -8000h + JL ESSIRQHandlerClip1 + Cmp EAX, 7FFFh + JG ESSIRQHandlerClip2 + +ESSIRQHandler7: + StosW ; } Memory write + + Add SI, BP + Dec DX + JNZ ESSIRQHandler6 + +WSSMixTransferEnd: + Pop DX + + Sub MixTransferRemaining, DX ; } Memory write + Sub BX, DX + JNZ ESSIRQHandler3 + + Mov MixTransferOffset, SI ; } Memory write + + Call RestoreEMSPageFrame + + Pop ES + Pop DS + PopAD + IRet + +ESSIRQHandlerClip1: + Mov AX, 8000h + Jmp ESSIRQHandler7 + +ESSIRQHandlerClip2: + Mov AX, 7FFFh + Jmp ESSIRQHandler7 + +WSSHFilterMonoClip1: + Mov AX, 8000h + Jmp ESSIRQHFilterMono2 + +WSSHFilterMonoClip2: + Mov AX, 7FFFh + Jmp ESSIRQHFilterMono2 + +WSSHFilterStereoClip1: + Mov AX, 8000h + Jmp ESSIRQHFilterStereo2 + +WSSHFilterStereoClip2: + Mov AX, 7FFFh + Jmp ESSIRQHFilterStereo2 + +WSSHFilterStereoClip3: + Mov AX, 8000h + Jmp ESSIRQHFilterStereo3 + +WSSHFilterStereoClip4: + Mov AX, 7FFFh + Jmp ESSIRQHFilterStereo3 + +WSS3QFilterMonoClip1: + Mov AX, 8000h + Jmp ESSIRQ3QFilterMono2 + +WSS3QFilterMonoClip2: + Mov AX, 7FFFh + Jmp ESSIRQ3QFilterMono2 + +WSS3QFilterStereoClip1: + Mov AX, 8000h + Jmp ESSIRQ3QFilterStereo2 + +WSS3QFilterStereoClip2: + Mov AX, 7FFFh + Jmp ESSIRQ3QFilterStereo2 + +WSS3QFilterStereoClip3: + Mov AX, 8000h + Jmp ESSIRQ3QFilterStereo3 + +WSS3QFilterStereoClip4: + Mov AX, 7FFFh + Jmp ESSIRQ3QFilterStereo3 + +EndP ESSIRQHandler + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Add DI, Offset IRQData + Mov BX, [CS:DI] + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset ESSIRQHandler + + XChg [ES:BX], EAX + Mov OldESSIRQHandler, EAX + + Mov AX, IMR + And AX, [DI+2] + + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Pop ES + PopAD + + Ret + +EndP SetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Mov BX, [IRQData+DI] + + Mov EAX, OldESSIRQHandler + Mov [ES:BX], EAX + + Pop ES + PopAD + + Ret + +EndP ResetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StopAD1816 + + PushA + + Mov AL, 1 + Call AD1816RegisterIn + And BX, 07FFFh ; Disable PIE + Call AD1816RegisterOut + + Mov DX, CS:BasePort + Inc DX + In AL, DX + And AL, Not 80h + Out DX, AL + + Add DL, 7 + In AL, DX + And AL, Not 1 + Out DX, AL + + PopA + Ret + +EndP StopAD1816 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StartAD1816 + + PushA + Push ES + Push DS + + Push CS + Pop DS + Assume DS:Driver + + ; Setup DMA + Mov BX, DMASegment + Xor AX, AX + Mov DX, DMA + Mov DI, DMABUFFERLENGTH + Call SetDMA + + LES DI, ActualDMAPtr + Xor AX, AX + Mov CX, DMABUFFERLENGTH/2 + Rep StosW + + Mov MixBufferPos, 0 + Mov MixTransferRemaining, 0 + + Mov AL, 4 + Call AD1816RegisterIn + + Mov AL, 32 + Call AD1816RegisterIn + Or BX, 08000h + Call AD1816RegisterOut + + Mov AL, 2 ; Sample rate + Mov BX, MixSpeed + Call AD1816RegisterOut + + Mov AL, 8 ; DMA Size + Mov BX, DMASize + ShR BX, 2 + Dec BX + Call AD1816RegisterOut + + Mov DX, BasePort ; Wave Format + Add DL, 8 + + Mov AL, 00010001b + Cmp Stereo, 0 + JE StartAD1816A + + Or AL, 4 + +StartAD1816A: + Out DX, AL + + Mov AL, 1 ; Enable Playback interrupt + Call AD1816RegisterIn + Or BX, 8000h + Call AD1816RegisterOut + + Pop DS + Pop ES + PopA + + Ret + +EndP StartAD1816 + Assume DS:Nothing + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov SI, Offset RelocationTable + +RelocationFix: + LodsW + Test AX, AX + JZ RelocationEnd + Mov BX, AX + Mov [BX], DS + Jmp RelocationFix + + +RelocationEnd: + Call GetEMSPageFrame + Mov EMSPageFrame, AX + + In AL, 0A1h + Mov AH, AL + In AL, 21h + Mov IMR, AX + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + Mov DX, CmdLineMixSpeed + Mov AX, 44100 + + Test DX, DX + JZ ClipMixSpeed2 + + Mov AX, DX + Cmp AX, 11050 + JA ClipMixSpeed1 + + Mov AX, 11050 + +ClipMixSpeed1: + Cmp AX, 55200 + JB ClipMixSpeed2 + + Mov AX, 55200 + +ClipMixSpeed2: + Mov MixSpeed, AX + Mov DX, 2643 + Mul DX + Add AX, 0FFFFh + AdC DX, 2080 + + Mov BX, (DMABUFFERLENGTH*2)/16 + Add BX, DX + + ; Allocate MixSegment first + Mov AH, 48h + + Int 21h + JNC InitSound1 + +InitSoundNoMemory: + Mov SI, Offset ESSNoMemoryMsg + Ret + +InitSound1: + Mov MixSegment, AX + Add AX, DX + Mov DMASegment, AX + + Call SetIRQ + Call GetTempo + Call SetTempo + + Call UpdateSoundcardVariables + + Mov SI, Offset ESSMsg + + Mov AX, BasePort + Mov BX, IRQ + Mov CX, DMA + + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Call ResetIRQ + Call SetIRQ + + Mov SI, Offset ReInitMsg + Mov BX, 40 + Call SetInfoLine + + Mov AL, Stereo + Call SetStereo + + Pop ES + Pop DS + PopA + + Ret + +EndP ReInitSound + Assume DS:Nothing + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, IMR + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Mov AX, MixSegment + Test AX, AX + JZ UnInitSound1 + + Push AX + + Call StopAD1816 + Call ResetIRQ + + Pop ES + Mov AH, 49h ; Release MixSegment + Int 21h + + +UnInitSound1: + Call GotoHomeDirectory + + ; Now to save config into driver file. + Mov AX, 3D02h ; Read write access + Mov DX, Offset DriverName + Int 21h + JC SetMixMode1 + + Mov BX, AX + + Mov AX, 4200h + Xor CX, CX + Mov DX, Offset CONFIGURATIONOFFSET + Int 21h + JC SetMixMode2 + + Mov AH, 40h + Mov CX, CONFIGSIZE + Mov DX, Offset MixMode + Int 21h + +SetMixMode2: + Mov AH, 3Eh + Int 21h + +SetMixMode1: + Ret + +EndP UnInitSound + Assume DS:Nothing + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + + Ret + +EndP Poll + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Push AX + Push BX + Push DX + + Push BX + + Mov AX, MixSpeed + Mov BX, AX + Xor DX, DX + + ShL AX, 1 + RCL DX, 1 ; DX:AX = Mixspeed*2 + + ShR BX, 1 ; BX = Mixspeed/2 + + Add AX, BX + AdC DX, 0 ; DX:AX = Mixspeed*2.5 + + Pop BX ; BX = tempo + Div BX + + Mov BytesToMix, AX + + Pop DX + Pop BX + Pop AX + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + PushA + Push DS + + Mov BX, AX ; BX = MixVolume + Mov CS:MixVolume, BX + + Mov AX, CS:MixSegment + Test AX, AX + JZ SetMixVolume2 + + Mov DS, AX + + Mov CX, MIXTABLESIZE/2 + Mov SI, MIXTABLESIZE-2; Starting point - working backwards + +SetMixVolume1: + Mov AX, CX + + Dec AX ; AH = volume, AL = wave value. + Xor DX, DX + XChg AH, DL ; DL = Volume, AX = wave value + CBW + + IMul DX ; DX:AX = Volume * Wave Value + ; Ranges -8192->8128 + + IMul BX ; DX:AX = Volume * Wave Value * Mixing Volume + ; Ranges -1048576->1040384 + + Add AX, 64 + AdC DX, 0 + + ShRD AX, DX, 7 + Mov [SI], AX + Sub SI, 2 + + Loop SetMixVolume1 + +SetMixVolume2: + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS:RecalculateAllVolumes + + Pop DS + PopA + + Ret + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Mov CS:Stereo, AL + Cmp CS:MixSegment, 0 + JE SetStereo1 + + Call StopAD1816 + Call StartAD1816 + +SetStereo1: + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include loadsam.inc + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset ESSScreenList + + ClC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far + + Xor AH, AH + Mov AL, [CS:VolumeTable+DI] + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UpdateSoundcardVariables + + Mov AL, 4 + Mov BX, 3F3Fh + Sub BX, [Word Ptr CS:VolumeTable] + Call AD1816RegisterOut + + Mov AL, 39 + Call AD1816RegisterIn + Mov CL, [CS:VolumeTable+2] + And BX, 0110000111111111b + ShL CX, 9 + Or BX, CX + Call AD1816RegisterOut + + Mov AL, 14 + Xor BX, BX + Call AD1816RegisterOut + + Ret + +EndP UpdateSoundcardVariables + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far + + Push DS + Push DX + + Push CS + Pop DS + Assume DS:Driver + + Mov [VolumeTable+DI], AL + Call UpdateSoundcardVariables + + Pop DX + Pop DS + Ret + +EndP SetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. + +StopAfterPlay DW 0 +DefaultChannels DW 64 + DW 5 Dup (0) + + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/DEBUG.INC b/SoundDrivers/DEBUG.INC new file mode 100755 index 0000000..ef745d7 --- /dev/null +++ b/SoundDrivers/DEBUG.INC @@ -0,0 +1,101 @@ +; +; Debug macro. To write to the file, use "Trace " +; + +IF TRACEENABLED + +IF CREATENEWLOGFILE +FirstTime DB 0 +ENDIF + +LogFileName DB "Logfile.Txt", 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WriteDebugFile + + PushA + Push DS + + Push CS + Pop DS + + Mov DX, Offset LogFileName + +IF CREATENEWLOGFILE + + Cmp DS:FirstTime, 0 + JNE WriteDebugFile1 + + Mov AH, 3Ch + Xor CX, CX + Int 21h + JC WriteDebugFileEnd + + Mov DS:FirstTime, 1 + XChg AX, BX + Jmp WriteDebugFile2 + + WriteDebugFile1: + +ENDIF + Mov AX, 3D02h + Int 21h + JC WriteDebugFileEnd + + XChg AX, BX + + Mov AX, 4202h + Xor CX, CX + Xor DX, DX + Int 21h ; Move to end of file + +WriteDebugFile2: + Mov AH, 40h + Mov CX, 82 + Mov DX, SI + Int 21h + + Mov AH, 3Eh + Int 21h + +WriteDebugFileEnd: + Pop DS + PopA + Ret + +EndP WriteDebugFile + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Trace Macro LogMessage + Local X, Y + + PushF + Push SI + Jmp Y + X: + DB LogMessage + DB 80-($-Offset X) Dup (0) + DB 0Dh, 0Ah + Y: + Mov SI, Offset X + Call WriteDebugFile + Pop SI + PopF + + EndM + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +ELSE + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Trace Macro LogMessage + EndM + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +ENDIF + diff --git a/SoundDrivers/DMA.INC b/SoundDrivers/DMA.INC new file mode 100755 index 0000000..c9f1fa9 --- /dev/null +++ b/SoundDrivers/DMA.INC @@ -0,0 +1,113 @@ + +DMAData Label Byte +; Port/Mask, Port/Clear, Port/DMAMode, Address, Page, Count, Port/Mask + DB 0Ah, 4, 0Ch, 0, 0Bh, 58h, 87h, 0, 1, 0Ah, 0 + DB 0Ah, 5, 0Ch, 0, 0Bh, 59h, 83h, 2, 3, 0Ah, 1 + DB 0Ah, 6, 0Ch, 0, 0Bh, 5Ah, 81h, 4, 5, 0Ah, 2 + DB 0Ah, 7, 0Ch, 0, 0Bh, 5Bh, 82h, 6, 7, 0Ah, 3 + DB 0D4h, 4, 0D8h, 0, 0D6h, 58h, 8Fh, 0C0h, 0C2h, 0D4h, 0 + DB 0D4h, 5, 0D8h, 0, 0D6h, 59h, 8Bh, 0C4h, 0C6h, 0D4h, 1 + DB 0D4h, 6, 0D8h, 0, 0D6h, 5Ah, 89h, 0C8h, 0CAh, 0D4h, 2 + DB 0D4h, 7, 0D8h, 0, 0D6h, 5Bh, 8Ah, 0CCh, 0CEh, 0D4h, 3 + +ActualDMAPtr Label DWord +ActualDMAOffset DW 0 +ActualDMASegment DW 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetDMA ; BX:AX points to DMA buffer + ; DL = DMA Channel + ; DI = DMA Size + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov ActualDMASegment, BX + Mov ActualDMAOffset, AX + + Mov CH, BH + ShR CH, 4 + ShL BX, 4 + Add BX, AX + AdC CH, 0 + Mov SI, BX ; CH:BH:BL contains 24 bit DMA address + Neg SI + Cmp SI, DI + JA SetDMA1 + + Add ActualDMAOffset, SI + Add BX, SI + AdC CH, 0 + +SetDMA1: + Cmp DL, 3 + JBE SetDMA2 + + ShR DI, 1 + Push CX + ShR CH, 1 + Pop CX + RCR BX, 1 + +SetDMA2: + Mov AL, 11 + Mul DL + Mov SI, AX + Add SI, Offset DMAData + + Xor DX, DX + + LodsB ; Set mask + Mov DL, AL + LodsB + Out DX, AL + + LodsB ; Clear Ptrs + Mov DL, AL + LodsB + Out DX, AL + + LodsB ; Set Mode + Mov DL, AL + LodsB + Out DX, AL + + LodsB + Mov DL, AL ; DL = page port + Mov AL, CH + Out DX, AL + + LodsB + Mov DL, AL ; DL = address port + Mov AL, BL + Out DX, AL + Mov AL, BH + Out DX, AL + + LodsB + Mov DL, AL ; DL = count port + Mov AX, DI + Dec AX + Out DX, AL + Mov AL, AH + Out DX, AL + + LodsB ; Reset mask + Mov DL, AL + LodsB + Out DX, AL + + Pop DS + PopA + + Ret + +EndP SetDMA + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + diff --git a/SoundDrivers/DMANAI.INC b/SoundDrivers/DMANAI.INC new file mode 100755 index 0000000..31071d5 --- /dev/null +++ b/SoundDrivers/DMANAI.INC @@ -0,0 +1,113 @@ + +DMAData Label Byte +; Port/Mask, Port/Clear, Port/DMAMode, Address, Page, Count, Port/Mask + DB 0Ah, 4, 0Ch, 0, 0Bh, 08h, 87h, 0, 1, 0Ah, 0 + DB 0Ah, 5, 0Ch, 0, 0Bh, 09h, 83h, 2, 3, 0Ah, 1 + DB 0Ah, 6, 0Ch, 0, 0Bh, 0Ah, 81h, 4, 5, 0Ah, 2 + DB 0Ah, 7, 0Ch, 0, 0Bh, 0Bh, 82h, 6, 7, 0Ah, 3 + DB 0D4h, 4, 0D8h, 0, 0D6h, 08h, 8Fh, 0C0h, 0C2h, 0D4h, 0 + DB 0D4h, 5, 0D8h, 0, 0D6h, 09h, 8Bh, 0C4h, 0C6h, 0D4h, 1 + DB 0D4h, 6, 0D8h, 0, 0D6h, 0Ah, 89h, 0C8h, 0CAh, 0D4h, 2 + DB 0D4h, 7, 0D8h, 0, 0D6h, 0Bh, 8Ah, 0CCh, 0CEh, 0D4h, 3 + +ActualDMAPtr Label DWord +ActualDMAOffset DW 0 +ActualDMASegment DW 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetDMA ; BX:AX points to DMA buffer + ; DL = DMA Channel + ; DI = DMA Size + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov ActualDMASegment, BX + Mov ActualDMAOffset, AX + + Mov CH, BH + ShR CH, 4 + ShL BX, 4 + Add BX, AX + AdC CH, 0 + Mov SI, BX ; CH:BH:BL contains 24 bit DMA address + Neg SI + Cmp SI, DI + JA SetDMA1 + + Add ActualDMAOffset, SI + Add BX, SI + AdC CH, 0 + +SetDMA1: + Cmp DL, 3 + JBE SetDMA2 + + ShR DI, 1 + Push CX + ShR CH, 1 + Pop CX + RCR BX, 1 + +SetDMA2: + Mov AL, 11 + Mul DL + Mov SI, AX + Add SI, Offset DMAData + + Xor DX, DX + + LodsB ; Set mask + Mov DL, AL + LodsB + Out DX, AL + + LodsB ; Clear Ptrs + Mov DL, AL + LodsB + Out DX, AL + + LodsB ; Set Mode + Mov DL, AL + LodsB + Out DX, AL + + LodsB + Mov DL, AL ; DL = page port + Mov AL, CH + Out DX, AL + + LodsB + Mov DL, AL ; DL = address port + Mov AL, BL + Out DX, AL + Mov AL, BH + Out DX, AL + + LodsB + Mov DL, AL ; DL = count port + Mov AX, DI + Dec AX + Out DX, AL + Mov AL, AH + Out DX, AL + + LodsB ; Reset mask + Mov DL, AL + LodsB + Out DX, AL + + Pop DS + PopA + + Ret + +EndP SetDMA + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + diff --git a/SoundDrivers/DMASIRQ.INC b/SoundDrivers/DMASIRQ.INC new file mode 100755 index 0000000..df906c5 --- /dev/null +++ b/SoundDrivers/DMASIRQ.INC @@ -0,0 +1,116 @@ + +DMAData Label Byte +; Port/Mask, Port/Clear, Port/DMAMode, Address, Page, Count, Port/Mask + DB 0Ah, 4, 0Ch, 0, 0Bh, 58h, 87h, 0, 1, 0Ah, 0 + DB 0Ah, 5, 0Ch, 0, 0Bh, 59h, 83h, 2, 3, 0Ah, 1 + DB 0Ah, 6, 0Ch, 0, 0Bh, 5Ah, 81h, 4, 5, 0Ah, 2 + DB 0Ah, 7, 0Ch, 0, 0Bh, 5Bh, 82h, 6, 7, 0Ah, 3 + DB 0D4h, 4, 0D8h, 0, 0D6h, 58h, 8Fh, 0C0h, 0C2h, 0D4h, 0 + DB 0D4h, 5, 0D8h, 0, 0D6h, 59h, 8Bh, 0C4h, 0C6h, 0D4h, 1 + DB 0D4h, 6, 0D8h, 0, 0D6h, 5Ah, 89h, 0C8h, 0CAh, 0D4h, 2 + DB 0D4h, 7, 0D8h, 0, 0D6h, 5Bh, 8Ah, 0CCh, 0CEh, 0D4h, 3 + +ActualDMAPtr Label DWord +ActualDMAOffset DW 0 +ActualDMASegment DW 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetDMA ; BX:AX points to DMA buffer + ; DL = DMA Channel + ; DI = DMA Size + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov ActualDMASegment, BX + Mov ActualDMAOffset, AX + + Mov CH, BH + ShR CH, 4 + ShL BX, 4 + Add BX, AX + AdC CH, 0 + Mov SI, BX ; CH:BH:BL contains 24 bit DMA address + Neg SI + Cmp SI, DI + JA SetDMA1 + + Add ActualDMAOffset, SI + Add BX, SI + AdC CH, 0 + +SetDMA1: + Cmp DL, 3 + JBE SetDMA2 + + ShR DI, 1 + Push CX + ShR CH, 1 + Pop CX + RCR BX, 1 + +SetDMA2: + Mov AL, 11 + Mul DL + Mov SI, AX + Add SI, Offset DMAData + + Xor DX, DX + + LodsB ; Set mask + Mov DL, AL + LodsB + Out DX, AL + + LodsB ; Clear Ptrs + Mov DL, AL + LodsB + Out DX, AL + + LodsB ; Set Mode + Mov DL, AL + LodsB + Out DX, AL + + LodsB + Mov DL, AL ; DL = page port + Mov AL, CH + Out DX, AL + + LodsB + Mov DL, AL ; DL = address port + Mov AL, BL + Out DX, AL + Mov AL, BH + Out DX, AL + + LodsB + Mov DL, AL ; DL = count port + Mov AX, DI + Dec AX + Out DX, AL + Mov AL, AH + Out DX, AL + + Mov Byte Ptr [CS:DMAPort1], DL + Mov Byte Ptr [CS:DMAPort2], DL + + LodsB ; Reset mask + Mov DL, AL + LodsB + Out DX, AL + + Pop DS + PopA + + Ret + +EndP SetDMA + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + diff --git a/SoundDrivers/DRHEAD.INC b/SoundDrivers/DRHEAD.INC new file mode 100755 index 0000000..03186ab --- /dev/null +++ b/SoundDrivers/DRHEAD.INC @@ -0,0 +1,8 @@ + +ID DB "Impulse Tracker Advanced Sound Driver", 13, 10 + DB "Copyright (C) 1995-1998 Jeffrey Lim", 0 + DB 26 + + DB 126 - ($ - Offset ID) Dup (0) + +LengthOfDriver DW Offset EndDriver - Offset StartDriver diff --git a/SoundDrivers/ENVIVO.ASM b/SoundDrivers/ENVIVO.ASM new file mode 100755 index 0000000..f4198e1 --- /dev/null +++ b/SoundDrivers/ENVIVO.ASM @@ -0,0 +1,2300 @@ +; +; Windows Sound System Driver +; + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;********************************** + +STEREOENABLED EQU 1 +DMABUFFERLENGTH EQU 8192 +MIXRESOLUTION EQU 32 ; 32 bit mixing for +MIXTABLESIZE EQU 2*256*65 + +PNPSERIALID EQU 98B03C20h +PNPVENDORID EQU 8140D315h +PNPVENDORID2 EQU 8040D315h + +DMASize DW 2048 + +WSSMsg DB "Ensoniq SoundscapeVIVO Codec", 13 + DB "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, DMA ", 0FDh, "D", 0 + +WSSNoMemoryMsg DB "Ensoniq SoundscapeVIVO Codec", 13 + DB "Error: Insufficient memory", 0 + +ReinitMsg DB "Ensoqiq SoundscapeVIVO Codec reinitialised", 0 + +ConfigErrorMsg DB "Error saving configuration to ITVIVO.DRV", 0 +ConfigOKMsg DB "Configuration saved to ITVIVO.DRV", 0 + +DriverName DB "ITVIVO.DRV", 0 + +Forced DB 0 +Stereo DB 0 +MixVolume DW 0 + +BytesToMix DW 1000 +WSSMixConst DB 0 + +MixSegment DW 0 +DMASegment DW 0 + +MixTransferOffset DW 0 +MixTransferRemaining DW 0 + +CONFIGURATIONOFFSET EQU $+128 +CONFIGSIZE EQU 6 +MixMode DW 0 +MixModeOffset DW 0 +Filter DW 0 + +IMR DW 0 +OldWSSIRQHandler DD 0 + +FilterValue DD 0 +FilterValue2 DD 0 + +MixSpeedTable DW 5513, 41h + DW 6615, 4Fh + DW 8000, 40h + DW 9600, 4Eh + DW 11025, 43h + DW 16000, 42h + DW 18900, 45h + DW 22050, 47h + DW 27429, 44h + DW 32000, 46h + DW 33075, 4Dh + DW 37800, 49h + DW 44100, 4Bh + DW 48000, 4Ch + +IRQSetupTable DB 0, 0, 0, 0, 0, 0, 0, 8 + DB 0, 10h, 18h, 20h, 0, 0, 0, 0 + +DMASetupTable DB 1, 2, 0, 3, 0, 0, 0, 0 + +IRQData Label Word + DW 20h, 1111111111111110b ; IRQ 0 + DW 24h, 1111111111111101b ; IRQ 1 + DW 28h, 1111110111111011b ; IRQ 2 + DW 2Ch, 1111111111110111b ; IRQ 3 + DW 30h, 1111111111101111b ; IRQ 4 + DW 34h, 1111111111011111b ; IRQ 5 + DW 38h, 1111111110111111b ; IRQ 6 + DW 3Ch, 1111111101111111b ; IRQ 7 + DW 1C0h, 1111111011111011b ; IRQ 8 + DW 1C4h, 1111110111111011b ; IRQ 9 + DW 1C8h, 1111101111111011b ; IRQ 10 + DW 1CCh, 1111011111111011b ; IRQ 11 + DW 1D0h, 1110111111111011b ; IRQ 12 + DW 1D4h, 1101111111111011b ; IRQ 13 + DW 1D8h, 1011111111111011b ; IRQ 14 + DW 1DCh, 0111111111111011b ; IRQ 15 + +;********************************** +; WSS Registers +;********************************** + +CODEC_INDEX_LIC = 00 +CODEC_INDEX_RIC = 01h +CODEC_INDEX_LX1C = 02h +CODEC_INDEX_RX1C = 03h +CODEC_INDEX_LX2C = 04h +CODEC_INDEX_RX2C = 05h +CODEC_INDEX_LDC = 06h +CODEC_INDEX_RDC = 07h +CODEC_INDEX_CDF = 08h +CODEC_INDEX_INTF = 09h +CODEC_INDEX_PIN = 0Ah +CODEC_INDEX_TEST = 0Bh +CODEC_INDEX_MISC = 0Ch +CODEC_INDEX_DIGMIX = 0Dh +CODEC_INDEX_UPR_COUNT = 0Eh +CODEC_INDEX_LWR_COUNT = 0Fh + +CODEC_MCE = 40h + +LDC_LDM = 80h +LDC_LDA = 3Fh + +RDC_RDM = 80h +RDC_RDA = 3Fh + +CDF_STEREO = 10h + +INTF_PEN = 01h +INTF_CEN = 02h +INTF_SDC = 04h +INTF_ACAL = 08h +INTF_PPIO = 40h +INTF_CPIO = 80h + +PIN_IEN = 2 + +TEST_ORL = 03h +TEST_ORR = 0Ch +TEST_DRS = 10h +TEST_ACI = 20h +TEST_PUR = 40h +TEST_COR = 80h + +;********************************** + +WSS16ScreenList Label + DW 16 + DW Near Ptr IdleFunctionList + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr WSSHeaderLine + + DW Near Ptr DriverText + + DW Near Ptr MixModeText + DW Near Ptr MixModeButton1 ; 6 + DW Near Ptr MixModeButton2 ; + DW Near Ptr MixModeButton3 ; 8 + DW Near Ptr MixModeButton4 ; 9 + + DW Near Ptr FilterText + DW Near Ptr FilterButton1 ; 11 + DW Near Ptr FilterButton2 + DW Near Ptr FilterButton3 + + DW Near Ptr VolumeText + DW Near Ptr VolumeBox1 + + DW Near Ptr MasterVolumeLeft ; 16 + DW Near Ptr MasterVolumeRight ; 17 + + DW 0 + +WSSHeaderLine DW 10 + DB "Ensoniq SoundscapeVIVO Driver", 0 + +EmptyObject DW 1 + DB 0, 0 + DB 0 + DB 0 + +DriverText DW 1 + DB 26, 48 + DB 21h + DB "Ensoniq SoundscapeVIVO Driver 1.0 for Impulse Tracker", 0 + +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +IdleFunctionList DD 0 + DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +VolumeText DW 1 + DB 2, 14 + DB 20h + DB "Master Volume Left", 13 + DB "Master Volume Right" + DB 0 + +VolumeBox1 DW 0 + DB 21, 13, 31, 16 + DB 25 + +MasterVolumeLeft DW 9 + DB 22, 14 + DW 0, 63 + DW 9, 0 + DW 0FFFFh, 17, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +MasterVolumeRight DW 9 + DB 22, 15 + DW 0, 63 + DW 9, 1 + DW 16, 6, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +MixModeText DW 1 + DB 2, 18 + DB 20h + DB "Mixing Mode, Playback Frequency: ", 0FDh, "DHz", 0 +MixSpeed DW 48000 + +MixModeButton1 DW 2 + DW 17, 7, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment1 DW 0 + DW 0 + DW Offset SetMixMode +DriverSegment2 DW 0 + DB 3, 20, 32, 22, 8 + DB 0 + DB " 16 Bit, Non-Interpolated", 0 + +MixModeButton2 DW 2 + DW 6, 8, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment3 DW 0 + DW 2 + DW Offset SetMixMode +DriverSegment4 DW 0 + DB 3, 23, 32, 25, 8 + DB 0 + DB " 16 Bit, Interpolated", 0 + +MixModeButton3 DW 2 + DW 7, 9, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment5 DW 0 + DW 4 + DW Offset SetMixMode +DriverSegment6 DW 0 + DB 3, 26, 32, 28, 8 + DB 0 + DB " 32 Bit, Non-Interpolated", 0 + +MixModeButton4 DW 2 + DW 8, 11, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment7 DW 0 + DW 6 + DW Offset SetMixMode +DriverSegment8 DW 0 + DB 3, 29, 32, 31, 8 + DB 0 + DB " 32 Bit, Interpolated", 0 + +FilterText DW 1 + DB 2, 33 + DB 20h + DB "Filter mode", 0 + +FilterButton1 DW 2 + DW 9, 12, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment9 DW 0 + DW 0 + DW Offset SetFilter +DriverSegment10 DW 0 + DB 3, 35, 29, 37, 8 + DB 0 + DB " No Filter", 0 + +FilterButton2 DW 2 + DW 11, 13, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment11 DW 0 + DW 1 + DW Offset SetFilter +DriverSegment12 DW 0 + DB 3, 38, 29, 40, 8 + DB 0 + DB " 50% Filter", 0 + +FilterButton3 DW 2 + DW 12, 0FFFFh, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment13 DW 0 + DW 2 + DW Offset SetFilter +DriverSegment14 DW 0 + DB 3, 41, 29, 43, 8 + DB 0 + DB " 75% Filter", 0 + +VolumeTable DB 2 Dup (0) + +; ÄÄ MixingRoutines ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixBufferPos DW 0 + +include dma.inc +include mix.inc +include m12bit.mix +include m12biti.mix +include m32bit.mix +include m32biti.mix + +MixFunctionTables Label + +include m12bit.inc ; contains the tables +include m12biti.inc +include m32bit.inc +include m32biti.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +RelocationTable Label Word + DW Offset DriverSegment1, Offset DriverSegment2 + DW Offset DriverSegment3, Offset DriverSegment4 + DW Offset DriverSegment5, Offset DriverSegment6 + DW Offset DriverSegment7, Offset DriverSegment8 + DW Offset DriverSegment9, Offset DriverSegment10 + DW Offset DriverSegment11, Offset DriverSegment12 + DW Offset DriverSegment13, Offset DriverSegment14 + DW 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixMode Far + + Push CS + Pop ES + Mov DI, Offset MixMode + + Ret + +EndP GetMixMode + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetFilter Far + + Push CS + Pop ES + Mov DI, Offset Filter + + Ret + +EndP GetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetFilter Far + + Mov AX, [SI+22] + Mov CS:FilterValue, 0 + Mov CS:Filter, AX + ClI + Jmp SetMixModeChain + +EndP SetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WaitCoDec + + Push CX + + Mov CX, 0F000h + +WaitCoDec1: + In AL, DX + Test AL, AL + JNS WaitCoDec2 + Loop WaitCoDec1 + + StC + +WaitCoDec2: + Pop CX + Ret + +EndP WaitCoDec + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WaitAutoCalibration + + Push CX + Mov CX, 0F000h + +WaitAutoCalibration1: + Mov AL, CODEC_INDEX_TEST + Out DX, AL + Inc DX + In AL, DX + Dec DX + Test AL, TEST_ACI + JNZ WaitAutoCalibration2 + Loop WaitAutoCalibration1 + + StC + +WaitAutoCalibration2: + Pop CX + Ret + +EndP WaitAutoCalibration + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixMode Far + + Mov AX, [SI+22] + + ClI + + Mov CS:MixMode, AX + + Mov BX, 180 + Mul BX + Mov CS:MixModeOffset, AX + + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS:RecalculateAllVolumes + + StI + +SetMixModeChain: + Call GotoHomeDirectory + + ; Now to save config into driver file. + Push CS + Pop DS + Assume DS:Driver + + Mov AX, 3D02h ; Read write access + Mov DX, Offset DriverName + Mov SI, Offset ConfigErrorMsg + Int 21h + JC SetMixMode1 + + Mov BX, AX + + Mov AX, 4200h + Xor CX, CX + Mov DX, Offset CONFIGURATIONOFFSET + Int 21h + JC SetMixMode2 + + Mov AH, 40h + Mov CX, CONFIGSIZE + Mov DX, Offset MixMode + Int 21h + +SetMixMode2: + PushF + Mov AH, 3Eh + Int 21h + PopF + + JC SetMixMode1 + + Mov SI, Offset ConfigOKMsg + +SetMixMode1: + Mov BX, 40 + Call SetInfoLine + + Mov AX, 1 + Ret + +EndP SetMixMode + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetWSSMixConst ; Work out value.. and nearest + ; mixspeed value. + + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, CmdLineMixSpeed + Mov CX, MixSpeed + Test AX, AX + JZ GetWSSMixConst1 + + Mov CX, 64000 + Cmp AX, CX + JA GetWSSMixConst1 + + Mov CX, 8000 + Cmp AX, CX + JB GetWSSMixConst1 + + Mov CX, AX + +GetWSSMixConst1: ; CX = desired mixspeed + Mov SI, Offset MixSpeedTable + Mov DX, 14 ; 14 different available speeds + + Xor BX, BX + +GetWSSMixConst2: + LodsW + Cmp AX, BX + JB GetWSSMixConst3 + Cmp AX, CX + JA GetWSSMixConst3 + + Mov BX, AX + Mov DH, [SI] + +GetWSSMixConst3: + LodsW ; Add SI, 2 + Dec DL + JNZ GetWSSMixConst2 + + Mov MixSpeed, BX + Mov WSSMixConst, DH + + Pop DS + PopA + Ret + +EndP GetWSSMixConst + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PingWSS ; Check BasePort, DX = BasePort + ; Preserves DX, destroys AX + + Push DX + + Add DX, 6 + + In AL, DX + Xor AL, AL + Out DX, AL + + Dec DX + Dec DX + Call WaitCodec + JC PingWSSFailure + + In AL, DX + Test AL, AL + JS PingWSSFailure + + Mov AL, CODEC_INDEX_MISC + Out DX, AL + Inc DX ; DX = Data port + In AL, DX + Mov AH, AL ; AH = Revision + + Xor AL, AL ; Write 0 revision + Out DX, AL + In AL, DX + And AX, 8F8Fh + Cmp AL, AH + JNE PingWSSFailure + Dec DX ; DX = AD1848 baseport + + Mov AL, CODEC_MCE or CODEC_INDEX_INTF + Out DX, AL + Inc DX + Mov AL, INTF_ACAL or INTF_SDC + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_INTF + Out DX, AL + Inc DX + Mov AL, INTF_ACAL or INTF_SDC + Out DX, AL + Dec DX + + Call WaitAutoCalibration ; Returns carry if error + ; Carry clear if none. + +; JC PingWSSFailure + + Pop DX + Ret + +PingWSSFailure: + Pop DX + + StC + Ret + + +EndP PingWSS + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +PnP_SerialID DD 0 +PnP_VendorID DD 0 +PnP_ReadPort DW 0 +PnP_CSN DB 0 +PnP_CardFound DB 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_Delay + Assume DS:Driver + + Push AX CX + + Mov CX, 180h +PnP_Delay1: + In AL, 21h + Loop PnP_Delay1 + + Pop CX AX + Ret + +EndP PnP_Delay + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_WriteData + + Mov DX, 279h + Out DX, AL + + Mov AL, AH + Mov DH, 0Ah + Out DX, AL + Ret + +EndP PnP_WriteData + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_ReadData + + Mov DX, 279h + Out DX, AL + + Mov DX, PnP_ReadPort + In AL, DX + + Ret + +EndP PnP_ReadData + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_Isolate + + Mov AX, 402h + Call Pnp_WriteData ; Reset CSNs + +PnP_IsolateNextCard: + Mov AX, 0003h + Call PnP_WriteData ; Wake[0] + + Mov AX, PnP_ReadPort + ShL AX, 6 + Xor AL, AL + Call PnP_WriteData ; Set Read Data port. + + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + + Mov AL, 1 ; Serial Isolation + Mov DX, 279h + Out DX, AL + + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + + Mov BL, 6Ah + Mov CX, 64 + Mov DX, PnP_ReadPort + + ClI + +PnP_Isolate1: + ShR PnP_SerialID, 1 + RCR PnP_VendorID, 1 + + Mov BH, BL + ShR BH, 1 + Xor BH, BL + ShR BX, 1 + + In AL, DX + Mov AH, AL + Call PnP_Delay + In AL, DX + Call PnP_Delay + + Cmp AX, 55AAh + JNE PnP_Isolate2 + + Xor BL, 80h + Or PnP_SerialID, 80000000h + +PnP_Isolate2: + Dec CX + JNZ PnP_Isolate1 + + Mov CX, 8 + Xor BH, BH + +PnP_Isolate3: + ShR BH, 1 + + In AL, DX + Mov AH, AL + Call PnP_Delay + In AL, DX + Call PnP_Delay + Cmp AX, 55AAh + JNE PnP_Isolate4 + + Or BH, 80h + +PnP_Isolate4: + Dec CX + JNZ PnP_Isolate3 + + StI + + Cmp BL, BH ; Matching Checksum? + JNE PnP_IsolateFinished + + ; assign CSN + Inc PnP_CSN + + Mov AL, 6 + MOv AH, PnP_CSN + Call PnP_WriteData + + Cmp PnP_VendorID, PNPVENDORID2 + JE VendorAlsoOK + Cmp PnP_VendorID, PNPVENDORID + JNE PnP_IsolateNextCard +; Cmp PnP_SerialID, PNPSERIALID +; JNE PnP_IsolateNextCard + +VendorAlsoOK: + Mov AL, 3 + Call PnP_WriteData + + Mov AX, 07h ; Configuration device + Call PnP_WriteData + + Mov AL, 62h + Call PnP_ReadData + Mov AH, AL + Mov AL, 63h + Call PnP_ReadData ; AX = address. + + Test AX, AX + JZ PnP_IsolateNextCard + + Cmp BasePort, 0FFFFh + JE PnPBasePortOK + + Cmp BasePort, AX + JNE PnP_IsolateNextCard + +PnPBasePortOK: + Mov BasePort, AX + + Mov AL, 70h + Call PnP_ReadData ; AL[3:0] = IRQ + And AX, 15 + JZ PnP_IsolateNextCard + Mov IRQ, AX + + Mov AL, 74h + Call PnP_ReadData ; AL[2:0] = DMA + And AX, 7 + Cmp AL, 4 + JE PnP_IsolateNextCard + Mov DMA, AX + + Mov Pnp_CardFound, 1 + Jmp PnP_IsolateNextCard + +PnP_IsolateFinished: + Mov AL, PnP_CSN + ShL AL, 1 + Or AL, PnP_CardFound + + Ret + +EndP PnP_Isolate + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far ; returns carry clear if succesful + + Push CS + Pop DS + + Xor AL, AL + Mov DX, 279h + Out DX, AL + Out DX, AL + + Mov AL, 6Ah ; Starting value + Mov CX, 32 + +PnP_InitiationKeyLoop: + Out DX, AL + + Mov AH, AL + ShR AH, 1 + Xor AH, AL + ShR AX, 1 + + Dec CX + JNZ PnP_InitiationKeyLoop + +; Try three ports before concluding no PnP cards: 20Fh, 27Bh, 213h + +PnP_DetectCardPort1: + Mov PnP_ReadPort, 20Fh + Call PnP_Isolate + JZ PnP_DetectCardPort2 + Test AL, 1 + JZ PnP_DetectCardNotFound + Jmp PnP_DetectCardFound + +PnP_DetectCardPort2: + Mov PnP_ReadPort, 27Bh + Call PnP_Isolate + JZ PnP_DetectCardPort3 + Test AL, 1 + JZ PnP_DetectCardNotFound + Jmp PnP_DetectCardFound + +PnP_DetectCardPort3: + Mov PnP_ReadPort, 213h + Call PnP_Isolate + Test AL, 1 + JNZ PnP_DetectCardFound + +PnP_DetectCardNotFound: + StC + Mov AX, 202h + Call PnP_WriteData + Ret + +PnP_DetectCardFound: + ClC + +PnP_DetectEnd: ; Return PnP to wait for key state + Mov AX, 202h + Call PnP_WriteData + + Mov DX, BasePort + Add DX, 4 + + Mov AL, CODEC_INDEX_RDC + Out DX, AL + Inc DX + In AL, DX + Mov AH, AL + Dec DX + + Mov AL, CODEC_INDEX_LDC + Out DX, AL + Inc DX + In AL, DX + And AX, 3F3Fh + Neg AL + Neg AH + Add AL, 3Fh + Add AH, 3Fh + Mov [Word Ptr VolumeTable], AX + + Mov EAX, 'Jeff' + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixModeTable Label Word + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + +Proc MixSamples ; Given DS:SI = info tables, CX = numchannels + + ; 1. Clean buffer + ; + update variables + ; 2. Update parameters + ; 3. Mix func + ; 4. Return + + Push CX + + Mov CX, BytesToMix + Mov ES, MixSegment + Mov DI, MIXTABLESIZE + Xor EAX, EAX + Mov DX, CX + Add CX, CX + + Mov MixTransferOffset, DI ; } Memory write + + Cmp Stereo, 0 + JE MixSamples1 + + Mov DX, CX + +MixSamples1: + Rep StosD ; } Memory write + Mov MixTransferRemaining, DX ; } + + Pop CX + +MixSamples2: + Test Byte Ptr [SI], 1 + JZ MixSamplesEnd2 + Cmp Byte Ptr [SI+36h], 100 + JE MixSamplesEnd2 + + Push CX + Mov CX, [SI] + + Test CH, 2 + JZ MixSamples3 + And Byte Ptr [SI], Not 1 + + Jmp MixSamplesEnd +; Cmp MixMode, 8 ; Is it volume ramping? +; JB MixSamplesEnd + +MixSamples3: + Test CL, 20h ; New freq? + JZ MixSamples5 + + Mov AX, [SI+10h] + Mov DX, [SI+12h] + Mov BX, MixSpeed + Cmp DX, BX + JAE MixSamplesHandleError + + Div BX + ShL EAX, 16 + Xor AX, AX + Div BX + Mov STEPVALUE, EAX + +MixSamples4: + Test CH, 1 + JZ MixSamples5 + + Mov DWord Ptr [SI+1Ch], 0 ; Current Volume = 0 + ; for volume sliding. +MixSamples5: + Test CX, 8440h ; New volume or panning? + JZ MixSamplesMix + + Xor AX, AX + Test CH, 8 ; Muted? + JNZ MixModeCommon + + Mov BX, MixMode + Add BL, Stereo + Add BX, BX + Jmp [CS:MixModeTable+BX] + +Mix0Mode: ; 16-bit mixing, no interpolation +Mix0ModeMono: ; and 16-bit mixing, interpolation + Mov AL, [SI+20h] + ShR AL, 1 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 30 ; Use left only-mixing for mono + Jmp MixModeCommon + +Mix0ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix0ModeSurround + + Mul Byte Ptr [SI+20h] ; Final volume + Add AX, 64 + ShR AX, 7 + Mov [SI+0Ch], AX ; Store into right volume + + Mov AL, 64 + Sub AL, [SI+37h] + Mul Byte Ptr [SI+20h] + Add AX, 64 + ShR AX, 7 + Mov [SI+0Eh], AX ; Left volume + + Mov CH, AL ; CH = left volume + Mov CL, [SI+0Ch] ; CL = right volume + Mov AX, 0 + + Test CX, CX + JZ MixModeCommon + + Mov AL, 30 ; Left only... + Test CL, CL + JZ MixModeCommon + + Mov AL, 60 + Test CH, CH + JZ MixModeCommon + + Mov AL, 90 + Cmp CL, CH + JZ MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix0ModeSurround: + Mov AL, [SI+20h] + ShR AL, 2 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 150 ; Surround + Jmp MixModeCommon + +Mix6ModeMono: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 8 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Test AX, AX + JZ MixModeCommon + Mov AX, 30 + Jmp MixModeCommon + +Mix6ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix6ModeSurround + + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Ch], AX ; Store into right volume + Mov BX, AX + ShL EAX, 16 + + Mov AL, 64 ; Do left volume + Sub AL, [SI+37h] ; AL = 64-FinalPan + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Eh], AX + + Mov ECX, EAX + + ; BX = right volume + ; CX = Left volume + Mov AX, 0 + Test ECX, ECX + JZ MixModeCommon + + Mov AL, 30 + Test BX, BX + JZ MixModeCommon + + Mov AL, 60 + Test CX, CX + JZ MixModeCommon + + Mov AL, 90 + Cmp CX, BX + JE MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix6ModeSurround: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 9 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + JZ MixModeCommon + Mov AX, 150 + Jmp MixModeCommon + +MixModeCommon: ; Requires AX = 30/60/90 etc. depending + ; On mixing mode type. + ; This will add 180 for 16-bit, + ; And sort out loop types. + Mov BL, [SI+0Ah] + Test Byte Ptr [SI+18h], 2 ; 16 bit? + JZ MixModeCommon1 + + Add AX, 180 + +MixModeCommon1: + Cmp BL, 8 + JB MixModeCommon3 ; No loop + JE MixModeCommon2 ; Forwards loop + + Add AX, 10 + +MixModeCommon2: + Add AX, 10 + +MixModeCommon3: + Add AX, Offset MixFunctionTables + Add AX, MixModeOffset + Mov [SI+8], AX ; Offset... + +MixSamplesMix: + Mov BX, [SI+8] ; BX = offset into + Mov EAX, [CS:BX+2] + Mov DWord Ptr PreMixFunction, EAX + Mov EAX, [CS:BX+6] + Mov DWord Ptr MixFunctionSeparateBackwards, EAX + + Mov AX, BytesToMix + Mov MixBlockSize, AX + Mov MixBufferOffset, MIXTABLESIZE + + Mov EAX, CURRENTPOSITION + Mov OLDPOSITION, EAX + + Call Word Ptr [CS:BX] + + And Word Ptr [SI], 0111100010001101b + Jmp MixSamplesEnd + +MixSamplesHandleError: + Mov Word Ptr [SI], 200h + + Test Byte Ptr [SI+3Ah], 80h + JNZ MixSamplesEnd + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Turn off channel + +MixSamplesEnd: + Pop CX + +MixSamplesEnd2: + Add SI, 128 + Dec CX + JNZ MixSamples2 + + Ret + +EndP MixSamples + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WSSIRQHandler + + PushAD + Push DS + Push ES + + ClD + + Mov AX, CS + Mov DS, AX + Assume DS:Driver + + Mov DX, [BasePort] + Add DX, 6 + In AL, DX + Test AL, 1 + JZ WSSAckIRQ2 + + Xor AL, AL + Out DX, AL + +WSSAckIRQ2: + Mov AL, 20h + Cmp IRQ, 8 + JB WSSAckIRQ1 + + Out 0A0h, AL + +WSSAckIRQ1: + Out 20h, AL + + Mov AX, MixBufferPos + Mov BX, AX + Mul DMASize + Cmp AX, DMABUFFERLENGTH + JB WSSIRQHandler2 + + Xor AX, AX + Xor BX, BX + +WSSIRQHandler2: + Inc BX + Mov MixBufferPos, BX + + CLD + + + ; OK... time to get next block + ; Check whether stereo thing is on.. + ; + LES DI, [ActualDMAPtr] + Add DI, AX + + Mov BX, DMASize ; BX = bytes required + ShR BX, 1 + ; BX = samples required + Mov BP, 8 ; Skip for mono + Mov CL, 14 ; Shift for mono + + Cmp Stereo, 0 + JE WSSIRQHandlerMono + + Mov BP, 4 ; Stereo skip value. + Dec CL + +WSSIRQHandlerMono: + Call SaveEMSPageFrame + + Cmp MixTransferRemaining, 0 + JNE WSSIRQHandler4 + Assume DS:Nothing + +WSSIRQHandler3: + Push BX + Push CX + Push BP + Push ES + Push DI + + Call Update + Call MixSamples + + Pop DI + Pop ES + Pop BP + Pop CX + Pop BX + +WSSIRQHandler4: + Mov DS, MixSegment + Mov SI, MixTransferOffset + Mov DX, BX ; DX = samples to transfer + Cmp DX, MixTransferRemaining + JBE WSSIRQHandler5 + + Mov DX, MixTransferRemaining + +WSSIRQHandler5: + Push DX + Cmp CS:Filter, 1 + JB WSSIRQHandler6 + JE WSSIRQHFilter + + Cmp CS:Stereo, 0 + JE WSSIRQ3QFilterMono + +WSSIRQ3QFilterStereo: + Push BX + + Mov EBX, FilterValue + Mov EBP, FilterValue2 + ShR DX, 1 + +WSSIRQ3QFilterStereo1: + Mov EAX, EBX + Mov ECX, EBP + Add EAX, [SI] + Add ECX, [SI+4] + SAR EAX, 1 + SAR ECX, 1 + Add EBX, EAX + Add EBP, ECX + SAR EBX, 1 + SAR EBP, 1 + + Mov EAX, EBX + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSS3QFilterStereoClip1 + Cmp EAX, 7FFFh + JG WSS3QFilterStereoClip2 + +WSSIRQ3QFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSS3QFilterStereoClip3 + Cmp EAX, 7FFFh + JG WSS3QFilterStereoClip4 + +WSSIRQ3QFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ WSSIRQ3QFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp WSSMixTransferEnd + +WSSIRQ3QFilterMono: + Push BX + + Mov EBX, FilterValue + +WSSIRQ3QFilterMono1: + Mov EAX, EBX + Add EAX, [SI] + SAR EAX, 1 + Add EBX, EAX + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL WSS3QFilterMonoClip1 + Cmp EAX, 7FFFh + JG WSS3QFilterMonoClip2 + +WSSIRQ3QFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ WSSIRQ3QFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp WSSMixTransferEnd + +WSSIRQHFilter: + Cmp CS:Stereo, 0 + JE WSSIRQHFilterMono + +WSSIRQHFilterStereo: + Push BX + + Mov EBX, FilterValue + Mov EBP, FilterValue2 + ShR DX, 1 + +WSSIRQHFilterStereo1: + Add EBX, [SI] + Add EBP, [SI+4] + + SAR EBX, 1 + SAR EBP, 1 + + Mov EAX, EBX + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSSHFilterStereoClip1 + Cmp EAX, 7FFFh + JG WSSHFilterStereoClip2 + +WSSIRQHFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSSHFilterStereoClip3 + Cmp EAX, 7FFFh + JG WSSHFilterStereoClip4 + +WSSIRQHFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ WSSIRQHFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp WSSMixTransferEnd + +WSSIRQHFilterMono: + Push BX + + Mov EBX, FilterValue + +WSSIRQHFilterMono1: + Add EBX, [SI] + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL WSSHFilterMonoClip1 + Cmp EAX, 7FFFh + JG WSSHFilterMonoClip2 + +WSSIRQHFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ WSSIRQHFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp WSSMixTransferEnd + +WSSIRQHandler6: + Mov EAX, [SI] + SAR EAX, CL + + Cmp EAX, -8000h + JL WSSIRQHandlerClip1 + Cmp EAX, 7FFFh + JG WSSIRQHandlerClip2 + +WSSIRQHandler7: + StosW ; } Memory write + + Add SI, BP + Dec DX + JNZ WSSIRQHandler6 + +WSSMixTransferEnd: + Pop DX + + Sub MixTransferRemaining, DX ; } Memory write + Sub BX, DX + JNZ WSSIRQHandler3 + + Mov MixTransferOffset, SI ; } Memory write + + Call RestoreEMSPageFrame + + Pop ES + Pop DS + PopAD + IRet + +WSSIRQHandlerClip1: + Mov AX, 8000h + Jmp WSSIRQHandler7 + +WSSIRQHandlerClip2: + Mov AX, 7FFFh + Jmp WSSIRQHandler7 + +WSSHFilterMonoClip1: + Mov AX, 8000h + Jmp WSSIRQHFilterMono2 + +WSSHFilterMonoClip2: + Mov AX, 7FFFh + Jmp WSSIRQHFilterMono2 + +WSSHFilterStereoClip1: + Mov AX, 8000h + Jmp WSSIRQHFilterStereo2 + +WSSHFilterStereoClip2: + Mov AX, 7FFFh + Jmp WSSIRQHFilterStereo2 + +WSSHFilterStereoClip3: + Mov AX, 8000h + Jmp WSSIRQHFilterStereo3 + +WSSHFilterStereoClip4: + Mov AX, 7FFFh + Jmp WSSIRQHFilterStereo3 + +WSS3QFilterMonoClip1: + Mov AX, 8000h + Jmp WSSIRQ3QFilterMono2 + +WSS3QFilterMonoClip2: + Mov AX, 7FFFh + Jmp WSSIRQ3QFilterMono2 + +WSS3QFilterStereoClip1: + Mov AX, 8000h + Jmp WSSIRQ3QFilterStereo2 + +WSS3QFilterStereoClip2: + Mov AX, 7FFFh + Jmp WSSIRQ3QFilterStereo2 + +WSS3QFilterStereoClip3: + Mov AX, 8000h + Jmp WSSIRQ3QFilterStereo3 + +WSS3QFilterStereoClip4: + Mov AX, 7FFFh + Jmp WSSIRQ3QFilterStereo3 + +EndP WSSIRQHandler + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Add DI, Offset IRQData + Mov BX, [CS:DI] + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset WSSIRQHandler + + XChg [ES:BX], EAX + Mov OldWSSIRQHandler, EAX + + Mov AX, IMR + And AX, [DI+2] + + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Pop ES + PopAD + + Ret + +EndP SetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Mov BX, [IRQData+DI] + + Mov EAX, OldWSSIRQHandler + Mov [ES:BX], EAX + + Pop ES + PopAD + + Ret + +EndP ResetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StopWSS + + Mov DX, BasePort + Add DX, 4 + + Mov AL, CODEC_INDEX_INTF + Out DX, AL + Inc DX + In AL, DX + And AL, Not INTF_PEN + Out DX, AL + + Inc DX + In AL, DX + Xor AL, AL + Out DX, AL + + Dec DX + Dec DX + + Mov AL, CODEC_INDEX_PIN + Out DX, AL + Inc DX + Xor AL, AL + Out DX, AL + + Ret + +EndP StopWSS + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StartWSS + + PushA + Push ES + Push DS + + Push CS + Pop DS + Assume DS:Driver + + ; Setup DMA + Mov BX, DMASegment + Xor AX, AX + Mov DX, DMA + Mov DI, DMABUFFERLENGTH + Call SetDMA + + LES DI, ActualDMAPtr + Xor AX, AX + Mov CX, DMABUFFERLENGTH/2 + Rep StosW + + Mov MixBufferPos, 0 + Mov MixTransferRemaining, 0 + + Mov DX, BasePort + Call PingWSS + + Add DX, 4 + + Mov AL, CODEC_INDEX_PIN + Out DX, AL + Inc DX + Mov AL, PIN_IEN + Out DX, AL + Dec DX + + Mov AH, WSSMixConst ; Set format/frequency + Cmp Stereo, 0 + JE StartWSS1 + + Or AH, CDF_STEREO + +StartWSS1: + Mov AL, CODEC_MCE or CODEC_INDEX_CDF + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Call WaitCodec + + Mov AL, CODEC_INDEX_CDF + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Call WaitAutoCalibration + + ; Start playback + Mov AL, CODEC_INDEX_LWR_COUNT + Out DX, AL + Inc DX + + Mov AX, DMASize + ShR AX, 1 + + Cmp Stereo, 0 + JE StartWSS2 + + ShR AX, 1 + +StartWSS2: + Dec AX + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_UPR_COUNT + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_INTF + Out DX, AL + Inc DX + In AL, DX + Or AL, INTF_PEN + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_LDC + Out DX, AL + Inc DX + In AL, DX + And AL, Not LDC_LDM + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_RDC + Out DX, AL + Inc DX + In AL, DX + And AL, Not RDC_RDM + Out DX, AL + Dec DX + + Pop DS + Pop ES + PopA + + Ret + +EndP StartWSS + Assume DS:Nothing + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov SI, Offset RelocationTable + +RelocationFix: + LodsW + Test AX, AX + JZ RelocationEnd + Mov BX, AX + Mov [BX], DS + Jmp RelocationFix + + +RelocationEnd: + Call GetEMSPageFrame + Mov EMSPageFrame, AX + + In AL, 0A1h + Mov AH, AL + In AL, 21h + Mov IMR, AX + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + Call GetWSSMixConst + + Mov AX, 2643 + Mul MixSpeed + Add AX, 0FFFFh + AdC DX, 2080 + + Mov BX, (DMABUFFERLENGTH*2)/16 + Add BX, DX + + ; Allocate MixSegment first + Mov AH, 48h + + Int 21h + JNC InitSound1 + +InitSoundNoMemory: + Mov SI, Offset WSSNoMemoryMsg + Ret + +InitSound1: + Mov MixSegment, AX + Add AX, DX + Mov DMASegment, AX + + Call SetIRQ + Call GetTempo + Call SetTempo + + Mov SI, Offset WSSMsg + + Mov AX, BasePort + Mov BX, IRQ + Mov CX, DMA + + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Call ResetIRQ + Call SetIRQ + + Mov SI, Offset ReInitMsg + Mov BX, 40 + Call SetInfoLine + + Mov AL, Stereo + Call SetStereo + + Pop ES + Pop DS + PopA + + Ret + +EndP ReInitSound + Assume DS:Nothing + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, IMR + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Mov AX, MixSegment + Test AX, AX + JZ UnInitSound1 + + Mov ES, AX + Mov AH, 49h ; Release MixSegment + Int 21h + + Call StopWSS + Call ResetIRQ + +UnInitSound1: + Ret + +EndP UnInitSound + Assume DS:Nothing + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + Ret + +EndP Poll + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Push AX + Push BX + Push DX + + Push BX + + Mov AX, MixSpeed + Mov BX, AX + Xor DX, DX + + ShL AX, 1 + RCL DX, 1 ; DX:AX = Mixspeed*2 + + ShR BX, 1 ; BX = Mixspeed/2 + + Add AX, BX + AdC DX, 0 ; DX:AX = Mixspeed*2.5 + + Pop BX ; BX = tempo + Div BX + + Mov BytesToMix, AX + + Pop DX + Pop BX + Pop AX + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + PushA + Push DS + + Mov BX, AX ; BX = MixVolume + Mov CS:MixVolume, BX + + Mov AX, CS:MixSegment + Test AX, AX + JZ SetMixVolume2 + + Mov DS, AX + + Mov CX, MIXTABLESIZE/2 + Mov SI, MIXTABLESIZE-2; Starting point - working backwards + +SetMixVolume1: + Mov AX, CX + + Dec AX ; AH = volume, AL = wave value. + Xor DX, DX + XChg AH, DL ; DL = Volume, AX = wave value + CBW + + IMul DX ; DX:AX = Volume * Wave Value + ; Ranges -8192->8128 + + IMul BX ; DX:AX = Volume * Wave Value * Mixing Volume + ; Ranges -1048576->1040384 + + Add AX, 64 + AdC DX, 0 + + ShRD AX, DX, 7 + Mov [SI], AX + Sub SI, 2 + + Loop SetMixVolume1 + +SetMixVolume2: + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS:RecalculateAllVolumes + + Pop DS + PopA + + Ret + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc RecalculateAllFrequencies + + Call GetChannelTables + +RecalculateAllFrequencies1: + Or Byte Ptr [SI], 32 + + Add SI, 128 + Dec CX + JNZ RecalculateAllFrequencies1 + + Ret + +EndP RecalculateAllFrequencies + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Mov CS:Stereo, AL + Cmp CS:MixSegment, 0 + JE SetStereo1 + + Call StopWSS + Call StartWSS + + Call RecalculateAllFrequencies + +SetStereo1: + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include loadsam.inc + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset WSS16ScreenList + + ClC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far + + Xor AH, AH + Mov AL, [CS:VolumeTable+DI] + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far + + Push DS + Push DX + + Push CS + Pop DS + Assume DS:Driver + + Mov [VolumeTable+DI], AL + + Mov DX, BasePort + Add DX, 4 + + Mov AL, CODEC_INDEX_LDC + Out DX, AL + Inc DX + Mov AX, 3F3Fh + Sub AX, [Word Ptr VolumeTable] + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_RDC + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Pop DX + Pop DS + Ret + +EndP SetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. + +StopAfterPlay DW 0 +DefaultChannels DW 64 + DW 5 Dup (0) + + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/EQUALIZE.INC b/SoundDrivers/EQUALIZE.INC new file mode 100755 index 0000000..c00c665 --- /dev/null +++ b/SoundDrivers/EQUALIZE.INC @@ -0,0 +1,161 @@ +; Do output filtering +; First copy old contents across +; Assumes destination is MixSegment:0 +; data order is lastvalues, coefficients, volumes + + Push CS + Pop DS + Assume DS:Driver + + Xor DI, DI + Mov SI, Offset LastFilter + + Mov EAX, [SI+40h] + Mov EBX, [SI+44h] + Mov ECX, [SI+48h] + Mov EDX, [SI+4Ch] + Or EAX, EBX + Or ECX, EDX + Or EAX, ECX + JZ NoEqualize + + Mov CX, 80/4 + Mov ES, MixSegment + + Rep MovsD + +; Now do filtering. + FNInit + Mov CX, BytesToMix + + Push ES + Pop DS + Assume DS:Nothing + + Mov SI, DMABUFFERLENGTH*2+80 + +OutputFilter1: + FILD DWord Ptr [SI] ; Left sample + FILD DWord Ptr [SI+4] ; R, L + + FLd DWord Ptr [DS:20h] ; LB, R, L + FMul ST, ST(2) ; L.LB, R, L + FLd DWord Ptr [DS:20h] ; LB, L.LB, R, L + FMul ST, ST(2) ; R.LB, L.LB, R, L + FLd DWord Ptr [DS:0] ; OL, R.LB, L.LB, R, L + FMul DWord Ptr [DS:24h] ; OL.LB, R.LB, L.LB, R, L + FLd DWord Ptr [DS:4] ; OR, OL.LB, R.LB, L.LB, R, L + FMul DWord Ptr [DS:24h] ; OR.LB, OL.LB, R.LB, L.LB, R, L + + FXCh ; OL.LB, OR.LB, R.LB, L.LB, R, L + FAddP ST(3), ST + FAdd ; RLB, LLB, R, L + + FLd DWord Ptr [DS:28h] ; MB, RLB, LLB, R, L + FMul ST, ST(4) ; L.MB, RLB, LLB, R, L + FLd DWord Ptr [DS:28h] ; MB, L.MB, RLB, LLB, R, L + FMul ST, ST(4) ; R.MB, L.MB, RLB, LLB, R, L + FLd DWord Ptr [DS:8] ; OL, R.MB, L.MB, RLB, LLB, R, L + FMul DWord Ptr [DS:2Ch] ; OL.MB, R.MB, L.MB, RLB, LLB, R, L + FLd DWord Ptr [DS:0Ch] ; OR, OL.MB, R.MB, L.MB, RLB, LLB, R, L + FMul DWord Ptr [DS:2Ch] ; OR.MB, OL.MB, R.MB, L.MB, RLB, LLB, R, L + + FXCh ; OL.MB, OR.MB, R.MB, L.MB, RLB, LLB, R, L + FAddP ST(3), ST + FAdd ; RMB, LMB, RLB, LLB, R, L + FXCh ST(3) ; LLB, LMB, RLB, RMB, R, L + FStP DWord Ptr [DS:0] + FStP DWord Ptr [DS:8] + FStP DWord Ptr [DS:4] + FStP DWord Ptr [DS:0Ch] + + FLd DWord Ptr [DS:30h] + FMul ST, ST(2) + FLd DWord Ptr [DS:30h] + FMul ST, ST(2) + FLd DWord Ptr [DS:10h] + FMul DWord Ptr [DS:34h] + FLd DWord Ptr [DS:14h] + FMul DWord Ptr [DS:34h] + + FXCh + FAddP ST(3), ST + FAdd + + FLd DWord Ptr [DS:38h] + FMul ST, ST(4) + FLd DWord Ptr [DS:38h] + FMul ST, ST(4) + FLd DWord Ptr [DS:18h] + FMul DWord Ptr [DS:3Ch] + FLd DWord Ptr [DS:1Ch] + FMul DWord Ptr [DS:3Ch] + + FXCh + FAddP ST(3), ST + FAdd + FXCh ST(3) + FStP DWord Ptr [DS:10h] + FStP DWord Ptr [DS:18h] + FStP DWord Ptr [DS:14h] + FStP DWord Ptr [DS:1Ch] ; R, L + +; For each one, output value += ((band value) - (previous band value)) * Volume + + FLd DWord Ptr [DS:18h] + FSub DWord Ptr [DS:10h] ; L4, R, L + FLd DWord Ptr [DS:1Ch] + FSub DWord Ptr [DS:14h] ; R4, L4, R, L + FLd DWord Ptr [DS:10h] + FSub DWord Ptr [DS:8] + FLd DWord Ptr [DS:14h] + FSub DWord Ptr [DS:0Ch] ; R3, L3, R4, L4, R, L + FLd DWord Ptr [DS:8] + FSub DWord Ptr [DS:0] + FLd DWord Ptr [DS:0Ch] + FSub DWord Ptr [DS:4] ; R2, L2, R3, L3, R4, L4, R, L + FXCh ST(5) ; L4, L2, R3, L3, R4, R2, R, L + FMul DWord Ptr [DS:4Ch] ; L4V, L2, R3, L3, R4, R2, R, L + FXCh ST(4) ; R4, L2, R3, L3, L4V, R2, R, L + FMul DWord Ptr [DS:4Ch] ; R4V, L2, R3, L3, L4V, R2, R, L + FXCh ST(3) ; L3, L2, R3, R4V, L4V, R2, R, L + FMul DWord Ptr [DS:48h] ; L3V, L2, R3, R4V, L4V, R2, R, L + FXCh ST(2) ; R3, L2, L3V, R4V, L4V, R2, R, L + FMul DWord Ptr [DS:48h] ; R3V, L2, L3V, R4V, L4V, R2, R, L + FXCh ; L2, R3V, L3V, R4V, L4V, R2, R, L + FMul DWord Ptr [DS:44h] ; L2V, R3V, L3V, R4V, L4V, R2, R, L + FXCh ST(5) ; R2, R3V, L3V, R4V, L4V, L2V, R, L + FMul DWord Ptr [DS:44h] ; R2V, R3V, L3V, R4V, L4V, L2V, R, L + FXCh ST(4) ; L4V, R3V, L3V, R4V, R2V, L2V, R, L + FAddP ST(7), ST ; R3V, L3V, R4V, R2V, L2V, R, L + FAddP ST(5), ST ; L3V, R4V, R2V, L2V, R, L + FAddP ST(3), ST + FAdd + FLd DWord Ptr [DS:0] + FMul DWord Ptr [DS:40h] ; L1V, RV, LV, R, L + FLd DWord Ptr [DS:4] ; + FMul DWord Ptr [DS:40h] ; R1V, L1V, RV, LV, R, L + FXCh ST(2) ; RV, L1V, R1V, LV, R, L + FAddP ST(4), ST ; L1V, R1V, LV, R, L + FAddP ST(4), ST ; R1V, LV, R, L + FAddP ST(2), ST + FAddP ST(2), ST + + FIStP DWord Ptr [SI+4] + FIStP DWord Ptr [SI] + + Add SI, 8 + Dec CX + JNZ OutputFilter1 + +; Transfer contents out + Push CS + Pop ES + + Mov DI, Offset LastFilter + Xor SI, SI + Mov CX, 32/4 + + Rep MovsD +; Finished output filtering! +NoEqualize: diff --git a/SoundDrivers/ES1688.ASM b/SoundDrivers/ES1688.ASM new file mode 100755 index 0000000..01d3a48 --- /dev/null +++ b/SoundDrivers/ES1688.ASM @@ -0,0 +1,2265 @@ +; +; ESS Technology's ES1688 Audiodrive chip +; + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;********************************** + +STEREOENABLED EQU 1 +DMABUFFERLENGTH EQU 8192 +MIXRESOLUTION EQU 32 ; 32 bit mixing for +MIXTABLESIZE EQU 2*256*65 + +;Debug DW 0 +;Debug2 DW 0 +ESSMsg DB "ES1688 AudioDrive found", 13 + DB "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, DMA ", 0FDh, "D", 0 + +ESSNoMemoryMsg DB "ES1688 AudioDrive found", 13 + DB "Error: Insufficient memory", 0 + +ReinitMsg DB "ES1688 AudioDrive reinitialised", 0 + +ConfigErrorMsg DB "Error saving configuration to ITES1688.DRV", 0 +ConfigOKMsg DB "Configuration saved to ITES1688.DRV", 0 + +DriverName DB "ITES1688.DRV", 0 + +ALIGN 4 +FilterValue DD 0 +FilterValue2 DD 0 +ESSMixConst DB 0, 0 + +DMASize DW 4096 ; Smaller gives better MIDI timing +ConfigPort DW 0 + +Forced DB 0 +Stereo DB 0 +MixVolume DW 0 + +BytesToMix DW 1000 + +MixSegment DW 0 +DMASegment DW 0 + +MixTransferOffset DW 0 +MixTransferRemaining DW 0 + +CONFIGURATIONOFFSET EQU $+128 +CONFIGSIZE EQU 6 +MixMode DW 0 +MixModeOffset DW 0 +Filter DW 0 + +IMR DW 0 +OldESSIRQHandler DD 0 + +IRQData Label Word + DW 20h, 1111111111111110b ; IRQ 0 + DW 24h, 1111111111111101b ; IRQ 1 + DW 28h, 1111110111111011b ; IRQ 2 + DW 2Ch, 1111111111110111b ; IRQ 3 + DW 30h, 1111111111101111b ; IRQ 4 + DW 34h, 1111111111011111b ; IRQ 5 + DW 38h, 1111111110111111b ; IRQ 6 + DW 3Ch, 1111111101111111b ; IRQ 7 + DW 1C0h, 1111111011111011b ; IRQ 8 + DW 1C4h, 1111110111111011b ; IRQ 9 + DW 1C8h, 1111101111111011b ; IRQ 10 + DW 1CCh, 1111011111111011b ; IRQ 11 + DW 1D0h, 1110111111111011b ; IRQ 12 + DW 1D4h, 1101111111111011b ; IRQ 13 + DW 1D8h, 1011111111111011b ; IRQ 14 + DW 1DCh, 0111111111111011b ; IRQ 15 + +ESSScreenList Label + DW 6 + DW Near Ptr IdleFunctionList + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr ESSHeaderLine + + DW Near Ptr DriverText + + DW Near Ptr MixModeText + DW Near Ptr MixModeButton1 ; 6 + DW Near Ptr MixModeButton2 ; + DW Near Ptr MixModeButton3 ; 8 + DW Near Ptr MixModeButton4 ; 9 + + DW Near Ptr FilterText + DW Near Ptr FilterButton1 ; 11 + DW Near Ptr FilterButton2 + DW Near Ptr FilterButton3 + +Comment ~ + + DW Near Ptr VolumeText + DW Near Ptr VolumeBox1 + + DW Near Ptr MasterVolumeLeft ; 16 + DW Near Ptr MasterVolumeRight ; 17 + +~ + + DW 0 + +ESSHeaderLine DW 10 + DB "ESS AudioDrive Driver", 0 + +EmptyObject DW 1 + DB 0, 0 + DB 0 + DB 0 + +DriverText DW 1 + DB 33, 48 + DB 21h + DB "ESS AudioDrive Driver 1.0 for Impulse Tracker", 0 + +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +IdleFunctionList DD 0 + DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +Comment ~ + +VolumeText DW 1 + DB 2, 14 + DB 20h + DB "Master Volume Left", 13 + DB "Master Volume Right" + DB 0 + +VolumeBox1 DW 0 + DB 21, 13, 31, 16 + DB 25 + +MasterVolumeLeft DW 14 + DB 22, 14 + DW 0, 15 + DW 9, 0 + DW 0FFFFh, 17, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 8 + +MasterVolumeRight DW 14 + DB 22, 15 + DW 0, 15 + DW 9, 1 + DW 16, 6, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 8 + +~ + +MixModeText DW 1 + DB 2, 14 + DB 20h + DB "Mixing Mode, Playback Frequency: ", 0FDh, "DHz", 0 +MixSpeed DW 44100 + +MixModeButton1 DW 2 + DW 0FFFFh, 7, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment1 DW 0 + DW 0 + DW Offset SetMixMode +DriverSegment2 DW 0 + DB 3, 16, 32, 18, 8 + DB 0 + DB " 16 Bit, Non-Interpolated", 0 + +MixModeButton2 DW 2 + DW 6, 8, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment3 DW 0 + DW 2 + DW Offset SetMixMode +DriverSegment4 DW 0 + DB 3, 19, 32, 21, 8 + DB 0 + DB " 16 Bit, Interpolated", 0 + +MixModeButton3 DW 2 + DW 7, 9, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment5 DW 0 + DW 4 + DW Offset SetMixMode +DriverSegment6 DW 0 + DB 3, 22, 32, 24, 8 + DB 0 + DB " 32 Bit, Non-Interpolated", 0 + +MixModeButton4 DW 2 + DW 8, 11, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment7 DW 0 + DW 6 + DW Offset SetMixMode +DriverSegment8 DW 0 + DB 3, 25, 32, 27, 8 + DB 0 + DB " 32 Bit, Interpolated", 0 + +FilterText DW 1 + DB 2, 29 + DB 20h + DB "Filter mode", 0 + +FilterButton1 DW 2 + DW 9, 12, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment9 DW 0 + DW 0 + DW Offset SetFilter +DriverSegment10 DW 0 + DB 3, 31, 29, 33, 8 + DB 0 + DB " No Filter", 0 + +FilterButton2 DW 2 + DW 11, 13, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment11 DW 0 + DW 1 + DW Offset SetFilter +DriverSegment12 DW 0 + DB 3, 34, 29, 36, 8 + DB 0 + DB " 50% Filter", 0 + +FilterButton3 DW 2 + DW 12, 0FFFFh, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment13 DW 0 + DW 2 + DW Offset SetFilter +DriverSegment14 DW 0 + DB 3, 37, 29, 39, 8 + DB 0 + DB " 75% Filter", 0 + +ALIGN 4 + +VolumeTable DB 2 Dup (0) +MIDIPort DW 0 + +MIDIBuffer DB 256 Dup (0) +MIDIBufferHead DB 0 +MIDIBufferTail DB 0 + +; ÄÄ MixingRoutines ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixBufferPos DW 0 + +include dmasirq.inc +include mix.inc +include m12bit.mix +include m12biti.mix +include m32bit.mix +include m32biti.mix + +MixFunctionTables Label + +include m12bit.inc ; contains the tables +include m12biti.inc +include m32bit.inc +include m32biti.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +RelocationTable Label Word + DW Offset DriverSegment1, Offset DriverSegment2 + DW Offset DriverSegment3, Offset DriverSegment4 + DW Offset DriverSegment5, Offset DriverSegment6 + DW Offset DriverSegment7, Offset DriverSegment8 + DW Offset DriverSegment9, Offset DriverSegment10 + DW Offset DriverSegment11, Offset DriverSegment12 + DW Offset DriverSegment13, Offset DriverSegment14 + DW 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ESSOut ; AL = data + ; DX = 2xCh + + Push AX + +ESSOut1: + In AL, DX + Test AL, AL + JS ESSOut1 + + Pop AX + Out DX, AL + + Ret + +EndP ESSOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ESSOut2 ; AL = data + ; DX = 2xCh + + Push AX + +ESSOut2A: + In AL, DX + Test AL, 80h + LoopNZ ESSOut2A + + Pop AX + Out DX, AL + + Ret + +EndP ESSOut2 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ESSIn2 + +ESSInA1: + In AL, DX + Test AL, 40h + LoopZ ESSInA1 + JZ ESSInA2 + + Add DL, 0Ah-0Ch ; DX = 2xAh -> Data read port + In AL, DX + Add DL, 0Ch-0Ah + + Ret + +ESSInA2: + Mov AL, 0FFh + Ret + +EndP ESSIn2 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ESSIn ; DX = 2xCh, returns AL + +ESSIn1: + In AL, DX + Test AL, 40h + JZ ESSIn1 + + Add DL, 0Ah-0Ch ; DX = 2xAh -> Data read port + In AL, DX + Add DL, 0Ch-0Ah + + Ret + +EndP ESSIn + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UARTOut ; AL = out + + Push DX + Push AX + + Mov DX, CS:MIDIPort + Inc DX + +UARTOut1: + In AL, DX + Test AL, 40h + JNZ UARTOut1 + + Pop AX + Dec DX + Out DX, AL + + Pop DX + Ret + +EndP UARTOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UARTIn ; returns AL + + Push DX + + Mov DX, CS:MIDIPort + Inc DX + +UARTIn1: + In AL, DX + Test AL, 80h + JNZ UARTIn1 + + Dec DX + In AL, DX + + Pop DX + Ret + +EndP UARTIn + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ESSReadMixerRegister ; AL = register to read + ; DX = 2xCh + + Add DL, 04-0Ch + Out DX, AL + Inc DX + In AL, DX + Add DL, 0Ch-05 + + Ret + +EndP ESSReadMixerRegister + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ESSReadRegister ; AH = register to read. + ; DX = 2xCh + ; returns AL + + Mov AL, 0C0h + Call ESSOut + Mov AL, AH + Call ESSOut + Call ESSIn + + Ret + +EndP ESSReadRegister + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixMode Far + + Push CS + Pop ES + Mov DI, Offset MixMode + + Ret + +EndP GetMixMode + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetFilter Far + + Push CS + Pop ES + Mov DI, Offset Filter + + Ret + +EndP GetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetFilter Far + + Mov AX, [SI+22] + Mov CS:FilterValue, 0 + Mov CS:Filter, AX + ClI + Jmp SetMixModeChain + +EndP SetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixMode Far + + Mov AX, [SI+22] + + ClI + + Mov CS:MixMode, AX + + Mov BX, 180 + Mul BX + Mov CS:MixModeOffset, AX + + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS:RecalculateAllVolumes + + StI + +SetMixModeChain: + Call GotoHomeDirectory + + ; Now to save config into driver file. + Push CS + Pop DS + Assume DS:Driver + + Mov AX, 3D02h ; Read write access + Mov DX, Offset DriverName + Mov SI, Offset ConfigErrorMsg + Int 21h + JC SetMixMode1 + + Mov BX, AX + + Mov AX, 4200h + Xor CX, CX + Mov DX, Offset CONFIGURATIONOFFSET + Int 21h + JC SetMixMode2 + + Mov AH, 40h + Mov CX, CONFIGSIZE + Mov DX, Offset MixMode + Int 21h + +SetMixMode2: + PushF + Mov AH, 3Eh + Int 21h + PopF + + JC SetMixMode1 + + Mov SI, Offset ConfigOKMsg + +SetMixMode1: + Mov BX, 40 + Call SetInfoLine + + Mov AX, 1 + Ret + +EndP SetMixMode + Assume DS:Nothing + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far + + Push CS + Pop DS + Assume DS:Driver + + Mov Forced, AL + + Mov AX, BasePort + Cmp AX, 0FFFFh + JE DetectCard1 + + Cmp AX, 210h + JB DetectCard9 + Cmp AX, 280h + JA DetectCard9 + + Call ResetDSP + JNC DetectCard2 + + Ret + +DetectCard1: + Mov AX, 210h + +DetectCard2: + Call ResetDSP + JNC DetectCard3 + Add AL, 10h + Cmp AL, 80h + JBE DetectCard2 + +DetectCard9: + StC + Ret + +DetectCard3: ; OK... DSP found. + ; Get DSP version + Mov BasePort, AX + + Mov DX, AX + Xor CX, CX + Add DL, 0Ch ; 2xCh -> Data ready to send... + + Mov AL, 0E1h + Call ESSOut2 + + Call ESSIn2 + Mov AH, AL ; AH = Major version number + Call ESSIn2 ; AL = Minor version number + + Cmp AX, 301h + JNE DetectCardFailure + + Mov AL, 0E7h + Call ESSOut2 + Call ESSIn2 + Mov AH, AL + Call ESSIn2 + + Cmp AH, 68h + JNE DetectCardReset + Cmp AL, 88h + JB DetectCardReset + Cmp AL, 90h + JAE DetectCardReset + ; We have an ES1688 Audiodrive chip! + +Comment ~ + Mov AL, 40h + Call ESSReadMixerRegister + ShL AL, 1 + And AX, 30h + Add AX, 300h + Mov MIDIPort, AX +~ + + Mov AH, 0B1h ; IRQ determination + Call ESSReadRegister + + Mov BX, 9 + And AL, 0Ch + JZ DetectCardIRQ + + Mov BX, 5 + Cmp AL, 4 + JE DetectCardIRQ + + Mov BX, 7 + Cmp AL, 8 + JE DetectCardIRQ + + Mov BX, 10 + Cmp AL, 0Ch + JNE DetectCardFailure + + +DetectCardIRQ: + Mov IRQ, BX + + Mov AH, 0B2h + Call ESSReadRegister + + Xor BX, BX + And AL, 0Ch + JZ DetectCardFailure + + Cmp AL, 4 + JE DetectCardDMA + + Inc BX + Cmp AL, 8 + JE DetectCardDMA + + Add BL, 2 + +DetectCardDMA: + Mov DMA, BX + + Mov EAX, 'Jeff' + ClC + Ret + +DetectCardReset: + Sub DL, 0Ch + Mov AX, DX + Call ResetDSP + +DetectCardFailure: + StC + Ret + + +EndP DetectCard + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetDSP Far ; AX = Port + + Push AX + Push CX + Push DX + + Mov DX, AX + Add DL, 6 + Mov AL, 3 + Out DX, AL + + In AL, DX + In AL, DX + In AL, DX + In AL, DX + + Xor AL, AL + Out DX, AL + + Add DL, 8 + Mov CX, 200 + +ResetDSP1: + In AL, DX + Test AL, AL + JS ResetDSP2 + Loop ResetDSP1 + Jmp ResetDSP3 + +ResetDSP2: + Sub DL, 4 + In AL, DX + Cmp AL, 0AAh + JE ResetDSP4 + Add DL, 4 + Loop ResetDSP1 + +ResetDSP3: + StC + +ResetDSP4: + Pop DX + Pop CX + Pop AX + Ret + +EndP ResetDSP + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixModeTable Label Word + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + +Proc MixSamples ; Given DS:SI = info tables, CX = numchannels + + ; 1. Clean buffer + ; + update variables + ; 2. Update parameters + ; 3. Mix func + ; 4. Return + + Push CX + + Mov CX, BytesToMix + Mov ES, MixSegment + Mov DI, MIXTABLESIZE + Xor EAX, EAX + Mov DX, CX + Add CX, CX + + Mov MixTransferOffset, DI ; } Memory write + + Cmp Stereo, 0 + JE MixSamples1 + + Mov DX, CX + +MixSamples1: + Rep StosD ; } Memory write + Mov MixTransferRemaining, DX ; } + + Pop CX + +MixSamples2: + Test Byte Ptr [SI], 1 + JZ MixSamplesEnd2 + Cmp Byte Ptr [SI+36h], 100 + JE MixSamplesEnd2 + + Push CX + Mov CX, [SI] + + Test CH, 2 + JZ MixSamples3 + And Byte Ptr [SI], Not 1 + + Jmp MixSamplesEnd +; Cmp MixMode, 8 ; Is it volume ramping? +; JB MixSamplesEnd + +MixSamples3: + Test CL, 20h ; New freq? + JZ MixSamples5 + + Mov AX, [SI+10h] + Mov DX, [SI+12h] + Mov BX, MixSpeed + Cmp DX, BX + JAE MixSamplesHandleError + + Div BX + ShL EAX, 16 + Xor AX, AX + Div BX + Mov STEPVALUE, EAX + +MixSamples4: + Test CH, 1 + JZ MixSamples5 + + Mov DWord Ptr [SI+1Ch], 0 ; Current Volume = 0 + ; for volume sliding. +MixSamples5: + Test CX, 8440h ; New volume or panning? + JZ MixSamplesMix + + Xor AX, AX + Test CH, 8 ; Muted? + JNZ MixModeCommon + + Mov BX, MixMode + Add BL, Stereo + Add BX, BX + Jmp [CS:MixModeTable+BX] + +Mix0Mode: ; 16-bit mixing, no interpolation +Mix0ModeMono: ; and 16-bit mixing, interpolation + Mov AL, [SI+20h] + ShR AL, 1 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 30 ; Use left only-mixing for mono + Jmp MixModeCommon + +Mix0ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix0ModeSurround + + Mul Byte Ptr [SI+20h] ; Final volume + Add AX, 64 + ShR AX, 7 + Mov [SI+0Ch], AX ; Store into right volume + + Mov AL, 64 + Sub AL, [SI+37h] + Mul Byte Ptr [SI+20h] + Add AX, 64 + ShR AX, 7 + Mov [SI+0Eh], AX ; Left volume + + Mov CH, AL ; CH = left volume + Mov CL, [SI+0Ch] ; CL = right volume + Mov AX, 0 + + Test CX, CX + JZ MixModeCommon + + Mov AL, 30 ; Left only... + Test CL, CL + JZ MixModeCommon + + Mov AL, 60 + Test CH, CH + JZ MixModeCommon + + Mov AL, 90 + Cmp CL, CH + JZ MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix0ModeSurround: + Mov AL, [SI+20h] + ShR AL, 2 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 150 ; Surround + Jmp MixModeCommon + +Mix6ModeMono: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 8 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Test AX, AX + JZ MixModeCommon + Mov AX, 30 + Jmp MixModeCommon + +Mix6ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix6ModeSurround + + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Ch], AX ; Store into right volume + Mov BX, AX + ShL EAX, 16 + + Mov AL, 64 ; Do left volume + Sub AL, [SI+37h] ; AL = 64-FinalPan + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Eh], AX + + Mov ECX, EAX + + ; BX = right volume + ; CX = Left volume + Mov AX, 0 + Test ECX, ECX + JZ MixModeCommon + + Mov AL, 30 + Test BX, BX + JZ MixModeCommon + + Mov AL, 60 + Test CX, CX + JZ MixModeCommon + + Mov AL, 90 + Cmp CX, BX + JE MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix6ModeSurround: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 9 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + JZ MixModeCommon + Mov AX, 150 + Jmp MixModeCommon + +MixModeCommon: ; Requires AX = 30/60/90 etc. depending + ; On mixing mode type. + ; This will add 180 for 16-bit, + ; And sort out loop types. + Mov BL, [SI+0Ah] + Test Byte Ptr [SI+18h], 2 ; 16 bit? + JZ MixModeCommon1 + + Add AX, 180 + +MixModeCommon1: + Cmp BL, 8 + JB MixModeCommon3 ; No loop + JE MixModeCommon2 ; Forwards loop + + Add AX, 10 + +MixModeCommon2: + Add AX, 10 + +MixModeCommon3: + Add AX, Offset MixFunctionTables + Add AX, MixModeOffset + Mov [SI+8], AX ; Offset... + +MixSamplesMix: + Mov BX, [SI+8] ; BX = offset into + Mov EAX, [CS:BX+2] + Mov DWord Ptr PreMixFunction, EAX + Mov EAX, [CS:BX+6] + Mov DWord Ptr MixFunctionSeparateBackwards, EAX + + Mov AX, BytesToMix + Mov MixBlockSize, AX + Mov MixBufferOffset, MIXTABLESIZE + + Mov EAX, CURRENTPOSITION + Mov OLDPOSITION, EAX + + Call Word Ptr [CS:BX] + + And Word Ptr [SI], 0111100010001101b + Jmp MixSamplesEnd + +MixSamplesHandleError: + Mov Word Ptr [SI], 200h + + Test Byte Ptr [SI+3Ah], 80h + JNZ MixSamplesEnd + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Turn off channel + +MixSamplesEnd: + Pop CX + +MixSamplesEnd2: + Add SI, 128 + Dec CX + JNZ MixSamples2 + + Ret + +EndP MixSamples + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc CheckMIDI + + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Xor BX, BX + Call UARTIn + Mov BL, [MIDIBufferTail] + + Cmp AL, 0F0h + JAE CheckMIDIEnd + + Inc BL + Cmp BL, MIDIBufferHead + JE CheckMIDIEnd + + Mov [MIDIBuffer+BX], AL + Mov [MIDIBufferTail], BL + +CheckMIDIEnd: + Pop DS + Ret + +EndP CheckMIDI + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ESSIRQHandler + + PushAD + Push DS + Push ES + + ClD + + Mov AX, CS + Mov DS, AX + Assume DS:Driver + +; Inc Debug + +Comment ~ + Mov DX, [ConfigPort] + Add DL, 6 + In AL, DX + Test AL, 8 + JZ ESSNoMIDI + + Push AX + Call CheckMIDI + Pop AX + +ESSNoMIDI: + Test AL, 1 + JZ ESSIRQEnd +~ + Mov DX, [BasePort] + Add DL, 0Eh + In AL, DX + + Mov AL, 20h + Cmp IRQ, 8 + JB WSSAckIRQ1 + + Out 0A0h, AL + +WSSAckIRQ1: + Out 20h, AL + +DMAPort1 EQU $+1 + In AL, 1 + Mov BL, AL +DMAPort2 EQU $+1 + In AL, 1 + Mov BH, AL + + Xor AX, AX + + Cmp BX, DMABUFFERLENGTH/2 + JB WSSIRQHandler1 + + Mov AX, DMABUFFERLENGTH/2 + +WSSIRQHandler1: + + ; OK... time to get next block + ; Check whether stereo thing is on.. + ; + LES DI, [ActualDMAPtr] + Add DI, AX + + Mov BX, DMASize ; BX = bytes required + ShR BX, 1 + ; BX = samples required + Mov BP, 8 ; Skip for mono + Mov CL, 14 ; Shift for mono + + Cmp Stereo, 0 + JE ESSIRQHandlerMono + + Mov BP, 4 ; Stereo skip value. + Dec CL + +ESSIRQHandlerMono: + Call SaveEMSPageFrame + + Cmp MixTransferRemaining, 0 + JNE ESSIRQHandler4 + Assume DS:Nothing + +ESSIRQHandler3: + Push BX + Push CX + Push BP + Push ES + Push DI + + Call Update + Call MixSamples + + Pop DI + Pop ES + Pop BP + Pop CX + Pop BX + +ESSIRQHandler4: + Mov DS, MixSegment + Mov SI, MixTransferOffset + Mov DX, BX ; DX = samples to transfer + Cmp DX, MixTransferRemaining + JBE ESSIRQHandler5 + + Mov DX, MixTransferRemaining + +ESSIRQHandler5: + Push DX + Cmp CS:Filter, 1 + JB ESSIRQHandler6 + JE ESSIRQHFilter + + Cmp CS:Stereo, 0 + JE ESSIRQ3QFilterMono + +ESSIRQ3QFilterStereo: + Push BX + + Mov EBX, FilterValue + Mov EBP, FilterValue2 + ShR DX, 1 + +ESSIRQ3QFilterStereo1: + Mov EAX, EBX + Mov ECX, EBP + Add EAX, [SI] + Add ECX, [SI+4] + SAR EAX, 1 + SAR ECX, 1 + Add EBX, EAX + Add EBP, ECX + SAR EBX, 1 + SAR EBP, 1 + + Mov EAX, EBX + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSS3QFilterStereoClip1 + Cmp EAX, 7FFFh + JG WSS3QFilterStereoClip2 + +ESSIRQ3QFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSS3QFilterStereoClip3 + Cmp EAX, 7FFFh + JG WSS3QFilterStereoClip4 + +ESSIRQ3QFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ ESSIRQ3QFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp WSSMixTransferEnd + +ESSIRQ3QFilterMono: + Push BX + + Mov EBX, FilterValue + +ESSIRQ3QFilterMono1: + Mov EAX, EBX + Add EAX, [SI] + SAR EAX, 1 + Add EBX, EAX + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL WSS3QFilterMonoClip1 + Cmp EAX, 7FFFh + JG WSS3QFilterMonoClip2 + +ESSIRQ3QFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ ESSIRQ3QFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp WSSMixTransferEnd + +ESSIRQHFilter: + Cmp CS:Stereo, 0 + JE ESSIRQHFilterMono + +ESSIRQHFilterStereo: + Push BX + + Mov EBX, FilterValue + Mov EBP, FilterValue2 + ShR DX, 1 + +ESSIRQHFilterStereo1: + Add EBX, [SI] + Add EBP, [SI+4] + + SAR EBX, 1 + SAR EBP, 1 + + Mov EAX, EBX + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSSHFilterStereoClip1 + Cmp EAX, 7FFFh + JG WSSHFilterStereoClip2 + +ESSIRQHFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSSHFilterStereoClip3 + Cmp EAX, 7FFFh + JG WSSHFilterStereoClip4 + +ESSIRQHFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ ESSIRQHFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp WSSMixTransferEnd + +ESSIRQHFilterMono: + Push BX + + Mov EBX, FilterValue + +ESSIRQHFilterMono1: + Add EBX, [SI] + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL WSSHFilterMonoClip1 + Cmp EAX, 7FFFh + JG WSSHFilterMonoClip2 + +ESSIRQHFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ ESSIRQHFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp WSSMixTransferEnd + +ESSIRQHandler6: + Mov EAX, [SI] + SAR EAX, CL + + Cmp EAX, -8000h + JL ESSIRQHandlerClip1 + Cmp EAX, 7FFFh + JG ESSIRQHandlerClip2 + +ESSIRQHandler7: + StosW ; } Memory write + + Add SI, BP + Dec DX + JNZ ESSIRQHandler6 + +WSSMixTransferEnd: + Pop DX + + Sub MixTransferRemaining, DX ; } Memory write + Sub BX, DX + JNZ ESSIRQHandler3 + + Mov MixTransferOffset, SI ; } Memory write + + Call RestoreEMSPageFrame + +ESSIRQEnd: + Pop ES + Pop DS + PopAD + IRet + +ESSIRQHandlerClip1: + Mov AX, 8000h + Jmp ESSIRQHandler7 + +ESSIRQHandlerClip2: + Mov AX, 7FFFh + Jmp ESSIRQHandler7 + +WSSHFilterMonoClip1: + Mov AX, 8000h + Jmp ESSIRQHFilterMono2 + +WSSHFilterMonoClip2: + Mov AX, 7FFFh + Jmp ESSIRQHFilterMono2 + +WSSHFilterStereoClip1: + Mov AX, 8000h + Jmp ESSIRQHFilterStereo2 + +WSSHFilterStereoClip2: + Mov AX, 7FFFh + Jmp ESSIRQHFilterStereo2 + +WSSHFilterStereoClip3: + Mov AX, 8000h + Jmp ESSIRQHFilterStereo3 + +WSSHFilterStereoClip4: + Mov AX, 7FFFh + Jmp ESSIRQHFilterStereo3 + +WSS3QFilterMonoClip1: + Mov AX, 8000h + Jmp ESSIRQ3QFilterMono2 + +WSS3QFilterMonoClip2: + Mov AX, 7FFFh + Jmp ESSIRQ3QFilterMono2 + +WSS3QFilterStereoClip1: + Mov AX, 8000h + Jmp ESSIRQ3QFilterStereo2 + +WSS3QFilterStereoClip2: + Mov AX, 7FFFh + Jmp ESSIRQ3QFilterStereo2 + +WSS3QFilterStereoClip3: + Mov AX, 8000h + Jmp ESSIRQ3QFilterStereo3 + +WSS3QFilterStereoClip4: + Mov AX, 7FFFh + Jmp ESSIRQ3QFilterStereo3 + +EndP ESSIRQHandler + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Add DI, Offset IRQData + Mov BX, [CS:DI] + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset ESSIRQHandler + + XChg [ES:BX], EAX + Mov OldESSIRQHandler, EAX + + Mov AX, IMR + And AX, [DI+2] + + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Pop ES + PopAD + + Ret + +EndP SetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Mov BX, [IRQData+DI] + + Mov EAX, OldESSIRQHandler + Mov [ES:BX], EAX + + Pop ES + PopAD + + Ret + +EndP ResetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetESSMixConst + + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, CmdLineMixSpeed + Mov CX, MixSpeed + Test AX, AX + JZ GetESSMixConst1 + + Mov CX, 22050 + Cmp AX, CX + JB GetESSMixConst1 + + Mov CX, 56821 + Cmp AX, CX + JA GetESSMixConst1 + + Mov CX, AX + +GetESSMixConst1: ; CX = mixspeed. + Mov DX, 0Ch + Mov AX, 236Ch ; DX:AX = 795.5kHz + Div CX + + Mov BX, AX + Neg AL + Mov ESSMixConst, AL + + Mov DX, 0Ch + Mov AX, 236Ch + Div BX + Mov MixSpeed, AX + + Pop DS + PopA + Ret + +EndP GetESSMixConst + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StartESS + + PushA + Push ES + Push DS + + Push CS + Pop DS + Assume DS:Driver + + ; Setup DMA + Mov BX, DMASegment + Xor AX, AX + Mov DX, DMA + Mov DI, DMABUFFERLENGTH + Call SetDMA + + LES DI, ActualDMAPtr + Xor AX, AX + Mov CX, DMABUFFERLENGTH/2 + Rep StosW + + Mov MixBufferPos, 0 + Mov MixTransferRemaining, 0 + + Mov AX, BasePort + Call ResetDSP + Mov DX, AX + Add DL, 0Ch + +; Extended Functions + + Mov AL, 0C6h + Call ESSOut + +; Autoinit DMA + + Mov AL, 0B8h + Call ESSOut + Mov AL, 4 + Call ESSOut + +; Stereo/Mono select + + Mov AH, 0A8h + Call ESSReadRegister + Mov AH, AL + Mov AL, 0A8h + Call ESSOut + Mov AL, AH + And AL, Not 3 + Or AL, 2 + Cmp Stereo, 0 + JE StartESS1 + + Xor AL, 3 + +StartESS1: + Call ESSOut + +; DMA mode + + Mov AL, 0B9h + Call ESSOut + Mov AL, 2 + Call ESSOut + +; Mixspeed + + Mov AL, 0A1h + Call ESSOut + Mov AL, ESSMixConst + Call ESSOut + +; Filter clock divider + Mov AL, 0A2h + Call ESSOut + + Mov AL, 0FEh + Call ESSOut + +; DMA counter + Mov CX, DMASize + Neg CX + + Mov AL, 0A4h + Call ESSOut + Mov AL, CL + Call ESSOut + Mov AL, 0A5h + Call ESSOut + Mov AL, CH + Call ESSOut + +; Initialise DAC + Mov AL, 0B6h + Call ESSOut + Mov AL, 0 + Call ESSOut + +; Configure DACs + + Mov AL, 0B7h + Call ESSOut + Mov AL, 71h + Call ESSOut + + Mov AL, 0B7h + Call ESSOut + + Mov AL, 0BCh + Cmp Stereo, 0 + JNE StartESS2 + + Mov AL, 0F4h + +StartESS2: + Call ESSOut + +; IRQ configuration + Mov AH, 0B1h + Call ESSReadRegister + Mov AH, AL + Mov AL, 0B1h + Call ESSOut + Mov AL, AH + And AL, 0Fh + Or AL, 50h + Call ESSOut + +; DMA configuration + Mov AH, 0B2h + Call ESSReadRegister + Mov AH, AL + Mov AL, 0B2h + Call ESSOut + Mov AL, AH + And AL, 0Fh + Or AL, 50h + Call ESSOut + +; Enable voice + Mov AL, 0D1h + Call ESSOut + +; Start transfer + Mov AH, 0B8h + Call ESSReadRegister + Mov AH, AL + Mov AL, 0B8h + Call ESSOut + Mov AL, AH + Or AL, 1 + Call ESSOut + +Comment ~ + +; Init UART + Mov DX, MIDIPort + Inc DX + Mov AL, 3Fh ; Intelligent mode. + Out DX, AL + +; Enable MIDI IRQ + Mov DX, BasePort + Add DL, 4 + Mov AX, 4064h + Out DX, AX + +~ + + Pop DS + Pop ES + PopA + + Ret + +EndP StartESS + Assume DS:Nothing + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov SI, Offset RelocationTable + +RelocationFix: + LodsW + Test AX, AX + JZ RelocationEnd + Mov BX, AX + Mov [BX], DS + Jmp RelocationFix + + +RelocationEnd: + Call GetEMSPageFrame + Mov EMSPageFrame, AX + + In AL, 0A1h + Mov AH, AL + In AL, 21h + Mov IMR, AX + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + Mov DX, BasePort + Add DL, 4 + Mov AL, 22h + Out DX, AL + Inc DX + In AL, DX + Mov AH, AL + And AX, 0FF0h + ShR AH, 1 + ShR AL, 5 + Mov Word Ptr [VolumeTable], AX + + Call GetESSMixConst + + Mov AX, 2643 + Mul MixSpeed + Add AX, 0FFFFh + AdC DX, 2080 + + Mov BX, (DMABUFFERLENGTH*2)/16 + Add BX, DX + + ; Allocate MixSegment first + Mov AH, 48h + + Int 21h + JNC InitSound1 + +InitSoundNoMemory: + Mov SI, Offset ESSNoMemoryMsg + Ret + +InitSound1: + Mov MixSegment, AX + Add AX, DX + Mov DMASegment, AX + + Call SetIRQ + Call GetTempo + Call SetTempo + + Mov SI, Offset ESSMsg + + Mov AX, BasePort + Mov BX, IRQ + Mov CX, DMA + + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Call ResetIRQ + Call SetIRQ + + Mov SI, Offset ReInitMsg + Mov BX, 40 + Call SetInfoLine + + Mov AL, Stereo + Call SetStereo + + Pop ES + Pop DS + PopA + + Ret + +EndP ReInitSound + Assume DS:Nothing + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, IMR + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Mov AX, MixSegment + Test AX, AX + JZ UnInitSound1 + + Mov ES, AX + Mov AH, 49h ; Release MixSegment + Int 21h + + Mov AX, BasePort + Call ResetDSP + Call ResetIRQ + +UnInitSound1: + Ret + +EndP UnInitSound + Assume DS:Nothing + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + Push CS + Pop DS + Assume DS:Driver +; +;DMAPort1 EQU $+1 +; In AL, 1 +; Mov BL, AL +;DMAPort2 EQU $+1 +; In AL, 1 +; Mov BH, AL +; +; Mov Debug2, BX + +Poll1: + Call [UARTBufferEmpty] + JNC PollEnd + + Xor BX, BX + + ClI + + Mov BL, MIDIBufferHead + Cmp BL, MIDIBufferTail + JZ PollEnd ; Nothing in queue + + Inc BL + Mov AL, [MIDIBuffer+BX] + Mov MIDIBufferHead, BL + + Call [UARTSend] + Jmp Poll1 + +PollEnd: + StI + + Ret + +EndP Poll + Assume DS:Nothing + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Push AX + Push BX + Push DX + + Push BX + + Mov AX, MixSpeed + Mov BX, AX + Xor DX, DX + + ShL AX, 1 + RCL DX, 1 ; DX:AX = Mixspeed*2 + + ShR BX, 1 ; BX = Mixspeed/2 + + Add AX, BX + AdC DX, 0 ; DX:AX = Mixspeed*2.5 + + Pop BX ; BX = tempo + Div BX + + Mov BytesToMix, AX + + Pop DX + Pop BX + Pop AX + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + PushA + Push DS + + Mov BX, AX ; BX = MixVolume + Mov CS:MixVolume, BX + + Mov AX, CS:MixSegment + Test AX, AX + JZ SetMixVolume2 + + Mov DS, AX + + Mov CX, MIXTABLESIZE/2 + Mov SI, MIXTABLESIZE-2; Starting point - working backwards + +SetMixVolume1: + Mov AX, CX + + Dec AX ; AH = volume, AL = wave value. + Xor DX, DX + XChg AH, DL ; DL = Volume, AX = wave value + CBW + + IMul DX ; DX:AX = Volume * Wave Value + ; Ranges -8192->8128 + + IMul BX ; DX:AX = Volume * Wave Value * Mixing Volume + ; Ranges -1048576->1040384 + + Add AX, 64 + AdC DX, 0 + + ShRD AX, DX, 7 + Mov [SI], AX + Sub SI, 2 + + Loop SetMixVolume1 + +SetMixVolume2: + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS:RecalculateAllVolumes + + Pop DS + PopA + + Ret + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Mov CS:Stereo, AL + Cmp CS:MixSegment, 0 + JE SetStereo1 + + Mov AX, BasePort + Call ResetDSP + Call StartESS + +SetStereo1: + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include loadsam.inc + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset ESSScreenList + + ClC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far + + Xor AH, AH + Mov AL, [CS:VolumeTable+DI] + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far + + Push DS + Push DX + + Push CS + Pop DS + Assume DS:Driver + + Mov [VolumeTable+DI], AL + + Mov DX, BasePort + Add DL, 4 + Mov AL, 22h + Out DX, AL + Mov AH, [VolumeTable] + ShL AH, 4 + Or AH, [VolumeTable+1] + ShL AH, 1 + Out DX, AX + + Pop DX + Pop DS + Ret + +EndP SetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. + +StopAfterPlay DW 0 +DefaultChannels DW 64 + DW 5 Dup (0) + + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/ES1688MX.ASM b/SoundDrivers/ES1688MX.ASM new file mode 100755 index 0000000..8996d51 --- /dev/null +++ b/SoundDrivers/ES1688MX.ASM @@ -0,0 +1,1751 @@ +; +; ESS Technology's ES1688 Audiodrive chip, MMX version. +; + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc +include mmx.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;********************************** + +STEREOENABLED EQU 1 +DMABUFFERLENGTH EQU 8192 +OUTPUTFILTERENABLED EQU 0 +MIXRESOLUTION EQU 32 ; 32 bit mixing for +MIXTABLESIZE EQU 2*256*65 + +;Debug DW 0 +;Debug2 DW 0 +ESSMsg DB "ES1688 AudioDrive MMX", 13 + DB "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, DMA ", 0FDh, "D", 0 + +ESSNoMemoryMsg DB "ES1688 AudioDrive MMX", 13 + DB "Error: Insufficient memory", 0 + +ReinitMsg DB "ES1688 AudioDrive reinitialised", 0 + +ConfigErrorMsg DB "Error saving configuration to ITES1688.MMX", 0 +ConfigOKMsg DB "Configuration saved to ITES1688.MMX", 0 + +DriverName DB "ITES1688.MMX", 0 + +ALIGN 4 +FPSave DB 128 Dup (0) +ESSMixConst DB 0, 0 + +DMASize DW 4096 ; Smaller gives better MIDI timing +ConfigPort DW 0 + +Forced DB 0 +Stereo DB 0 +MixVolume DW 0 + +BytesToMix DW 1000 + +MixSegment DW 0 + +MixTransferOffset DW 0 +MixTransferRemaining DW 0 + +CONFIGURATIONOFFSET EQU $+128 +CONFIGSIZE EQU 6 +MixMode DW 0 +MixModeOffset DW 0 +Filter DW 0 + +IMR DW 0 +OldESSIRQHandler DD 0 + +IRQData Label Word + DW 20h, 1111111111111110b ; IRQ 0 + DW 24h, 1111111111111101b ; IRQ 1 + DW 28h, 1111110111111011b ; IRQ 2 + DW 2Ch, 1111111111110111b ; IRQ 3 + DW 30h, 1111111111101111b ; IRQ 4 + DW 34h, 1111111111011111b ; IRQ 5 + DW 38h, 1111111110111111b ; IRQ 6 + DW 3Ch, 1111111101111111b ; IRQ 7 + DW 1C0h, 1111111011111011b ; IRQ 8 + DW 1C4h, 1111110111111011b ; IRQ 9 + DW 1C8h, 1111101111111011b ; IRQ 10 + DW 1CCh, 1111011111111011b ; IRQ 11 + DW 1D0h, 1110111111111011b ; IRQ 12 + DW 1D4h, 1101111111111011b ; IRQ 13 + DW 1D8h, 1011111111111011b ; IRQ 14 + DW 1DCh, 0111111111111011b ; IRQ 15 + +ESSScreenList Label + DW 6 + DW Near Ptr IdleFunctionList + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr ESSHeaderLine + + DW Near Ptr DriverText + + DW Near Ptr MixModeText + DW Near Ptr MixModeButton1 ; 6 + DW Near Ptr MixModeButton2 ; + DW Near Ptr MixModeButton3 ; 8 + DW Near Ptr MixModeButton4 ; 9 + +Comment ~ + + DW Near Ptr VolumeText + DW Near Ptr VolumeBox1 + + DW Near Ptr MasterVolumeLeft ; 16 + DW Near Ptr MasterVolumeRight ; 17 + +~ + + DW 0 + +ESSHeaderLine DW 10 + DB "ESS1688 AudioDrive MMX Driver", 0 + +EmptyObject DW 1 + DB 0, 0 + DB 0 + DB 0 + +DriverText DW 1 + DB 33, 48 + DB 21h + DB "ESS AudioDrive Driver 1.0 for Impulse Tracker", 0 + +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +IdleFunctionList DD 0 + DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +Comment ~ + +VolumeText DW 1 + DB 2, 14 + DB 20h + DB "Master Volume Left", 13 + DB "Master Volume Right" + DB 0 + +VolumeBox1 DW 0 + DB 21, 13, 31, 16 + DB 25 + +MasterVolumeLeft DW 14 + DB 22, 14 + DW 0, 15 + DW 9, 0 + DW 0FFFFh, 17, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 8 + +MasterVolumeRight DW 14 + DB 22, 15 + DW 0, 15 + DW 9, 1 + DW 16, 6, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 8 + +~ + +MixModeText DW 1 + DB 2, 14 + DB 20h + DB "Mixing Mode, Playback Frequency: ", 0FDh, "DHz", 0 +MixSpeed DW 44100 + DW 0 + +MixModeButton1 DW 2 + DW 0FFFFh, 7, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment1 DW 0 + DW 0 + DW Offset SetMixMode +DriverSegment2 DW 0 + DB 3, 16, 32, 18, 8 + DB 0 + DB " MMX, Non-Interpolated", 0 + +MixModeButton2 DW 2 + DW 6, 8, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment3 DW 0 + DW 1 + DW Offset SetMixMode +DriverSegment4 DW 0 + DB 3, 19, 32, 21, 8 + DB 0 + DB " MMX, Interpolated", 0 + +MixModeButton3 DW 2 + DW 7, 9, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment5 DW 0 + DW 2 + DW Offset SetMixMode +DriverSegment6 DW 0 + DB 3, 22, 32, 24, 8 + DB 0 + DB " MMX, Volume Ramped", 0 + +MixModeButton4 DW 2 + DW 8, 0FFFFh, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment7 DW 0 + DW 3 + DW Offset SetMixMode +DriverSegment8 DW 0 + DB 3, 25, 32, 27, 8 + DB 0 + DB " MMX, Filtered", 0 + +ALIGN 4 + +VolumeTable DB 2 Dup (0) +MIDIPort DW 0 + +MIDIBuffer DB 256 Dup (0) +MIDIBufferHead DB 0 +MIDIBufferTail DB 0 + +; ÄÄ MixingRoutines ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixBufferPos DW 0 + +include dmasirq.inc +include mix.inc + +include m32bitm.mix +include m32bitmi.mix +include m32bitmv.mix +include m32bitmf.mix + +ALIGN 2 + +MixFunctionTables Label + +include m32bitm.inc +include m32bitmi.inc +include m32bitmv.inc +include m32bitmf.inc +include mnomix.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +RelocationTable Label Word + DW Offset DriverSegment1, Offset DriverSegment2 + DW Offset DriverSegment3, Offset DriverSegment4 + DW Offset DriverSegment5, Offset DriverSegment6 + DW Offset DriverSegment7, Offset DriverSegment8 + DW 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ESSOut ; AL = data + ; DX = 2xCh + + Push AX + +ESSOut1: + In AL, DX + Test AL, AL + JS ESSOut1 + + Pop AX + Out DX, AL + + Ret + +EndP ESSOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ESSOut2 ; AL = data + ; DX = 2xCh + + Push AX + +ESSOut2A: + In AL, DX + Test AL, 80h + LoopNZ ESSOut2A + + Pop AX + Out DX, AL + + Ret + +EndP ESSOut2 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectMMX + + PushFD + Pop EAX + Mov EBX, EAX + Xor EAX, 00200000h + Push EAX + PopFD + PushFD + Pop EAX + Cmp EAX, EBX + JZ DetectMMXFail + + Mov EAX, 1 + DB 0Fh, 0A2h ; CPUID + Test EDX, 800000h + JZ DetectMMXFail + + ClC + Ret + +DetectMMXFail: + StC + Ret + +EndP DetectMMX + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ESSIn2 + +ESSInA1: + In AL, DX + Test AL, 40h + LoopZ ESSInA1 + JZ ESSInA2 + + Add DL, 0Ah-0Ch ; DX = 2xAh -> Data read port + In AL, DX + Add DL, 0Ch-0Ah + + Ret + +ESSInA2: + Mov AL, 0FFh + Ret + +EndP ESSIn2 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ESSIn ; DX = 2xCh, returns AL + +ESSIn1: + In AL, DX + Test AL, 40h + JZ ESSIn1 + + Add DL, 0Ah-0Ch ; DX = 2xAh -> Data read port + In AL, DX + Add DL, 0Ch-0Ah + + Ret + +EndP ESSIn + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UARTOut ; AL = out + + Push DX + Push AX + + Mov DX, CS:MIDIPort + Inc DX + +UARTOut1: + In AL, DX + Test AL, 40h + JNZ UARTOut1 + + Pop AX + Dec DX + Out DX, AL + + Pop DX + Ret + +EndP UARTOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UARTIn ; returns AL + + Push DX + + Mov DX, CS:MIDIPort + Inc DX + +UARTIn1: + In AL, DX + Test AL, 80h + JNZ UARTIn1 + + Dec DX + In AL, DX + + Pop DX + Ret + +EndP UARTIn + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ESSReadMixerRegister ; AL = register to read + ; DX = 2xCh + + Add DL, 04-0Ch + Out DX, AL + Inc DX + In AL, DX + Add DL, 0Ch-05 + + Ret + +EndP ESSReadMixerRegister + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ESSReadRegister ; AH = register to read. + ; DX = 2xCh + ; returns AL + + Mov AL, 0C0h + Call ESSOut + Mov AL, AH + Call ESSOut + Call ESSIn + + Ret + +EndP ESSReadRegister + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixMode Far + + Push CS + Pop ES + Mov DI, Offset MixMode + + Ret + +EndP GetMixMode + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixMode Far + + Mov AX, [SI+22] + + ClI + + Mov CS:MixMode, AX + + Mov BX, 60 + Mul BX + Mov CS:MixModeOffset, AX + + StI + +SetMixModeChain: + Call GotoHomeDirectory + + ; Now to save config into driver file. + Push CS + Pop DS + Assume DS:Driver + + Mov AX, 3D02h ; Read write access + Mov DX, Offset DriverName + Mov SI, Offset ConfigErrorMsg + Int 21h + JC SetMixMode1 + + Mov BX, AX + + Mov AX, 4200h + Xor CX, CX + Mov DX, Offset CONFIGURATIONOFFSET + Int 21h + JC SetMixMode2 + + Mov AH, 40h + Mov CX, CONFIGSIZE + Mov DX, Offset MixMode + Int 21h + +SetMixMode2: + PushF + Mov AH, 3Eh + Int 21h + PopF + + JC SetMixMode1 + + Mov SI, Offset ConfigOKMsg + +SetMixMode1: + Mov BX, 40 + Call SetInfoLine + + Mov AX, 1 + Ret + +EndP SetMixMode + Assume DS:Nothing + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far + + Push CS + Pop DS + Assume DS:Driver + + Mov Forced, AL + + Call DetectMMX + JC DetectCardFailure + + Mov AX, BasePort + Cmp AX, 0FFFFh + JE DetectCard1 + + Cmp AX, 210h + JB DetectCard9 + Cmp AX, 280h + JA DetectCard9 + + Call ResetDSP + JNC DetectCard2 + + Ret + +DetectCard1: + Mov AX, 210h + +DetectCard2: + Call ResetDSP + JNC DetectCard3 + Add AL, 10h + Cmp AL, 80h + JBE DetectCard2 + +DetectCard9: + StC + Ret + +DetectCard3: ; OK... DSP found. + ; Get DSP version + Mov BasePort, AX + + Mov DX, AX + Xor CX, CX + Add DL, 0Ch ; 2xCh -> Data ready to send... + + Mov AL, 0E1h + Call ESSOut2 + + Call ESSIn2 + Mov AH, AL ; AH = Major version number + Call ESSIn2 ; AL = Minor version number + + Cmp AX, 301h + JNE DetectCardFailure + + Mov AL, 0E7h + Call ESSOut2 + Call ESSIn2 + Mov AH, AL + Call ESSIn2 + + Cmp AH, 68h + JNE DetectCardReset + Cmp AL, 88h + JB DetectCardReset + Cmp AL, 90h + JAE DetectCardReset + ; We have an ES1688 Audiodrive chip! + +Comment ~ + Mov AL, 40h + Call ESSReadMixerRegister + ShL AL, 1 + And AX, 30h + Add AX, 300h + Mov MIDIPort, AX +~ + + Mov AH, 0B1h ; IRQ determination + Call ESSReadRegister + + Mov BX, 9 + And AL, 0Ch + JZ DetectCardIRQ + + Mov BX, 5 + Cmp AL, 4 + JE DetectCardIRQ + + Mov BX, 7 + Cmp AL, 8 + JE DetectCardIRQ + + Mov BX, 10 + Cmp AL, 0Ch + JNE DetectCardFailure + + +DetectCardIRQ: + Mov IRQ, BX + + Mov AH, 0B2h + Call ESSReadRegister + + Xor BX, BX + And AL, 0Ch + JZ DetectCardFailure + + Cmp AL, 4 + JE DetectCardDMA + + Inc BX + Cmp AL, 8 + JE DetectCardDMA + + Add BL, 2 + +DetectCardDMA: + Mov DMA, BX + + Mov EAX, 'Jeff' + ClC + Ret + +DetectCardReset: + Sub DL, 0Ch + Mov AX, DX + Call ResetDSP + +DetectCardFailure: + StC + Ret + + +EndP DetectCard + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetDSP Far ; AX = Port + + Push AX + Push CX + Push DX + + Mov DX, AX + Add DL, 6 + Mov AL, 3 + Out DX, AL + + In AL, DX + In AL, DX + In AL, DX + In AL, DX + + Xor AL, AL + Out DX, AL + + Add DL, 8 + Mov CX, 200 + +ResetDSP1: + In AL, DX + Test AL, AL + JS ResetDSP2 + Loop ResetDSP1 + Jmp ResetDSP3 + +ResetDSP2: + Sub DL, 4 + In AL, DX + Cmp AL, 0AAh + JE ResetDSP4 + Add DL, 4 + Loop ResetDSP1 + +ResetDSP3: + StC + +ResetDSP4: + Pop DX + Pop CX + Pop AX + Ret + +EndP ResetDSP + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include mmxmsam.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc CheckMIDI + + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Xor BX, BX + Call UARTIn + Mov BL, [MIDIBufferTail] + + Cmp AL, 0F0h + JAE CheckMIDIEnd + + Inc BL + Cmp BL, MIDIBufferHead + JE CheckMIDIEnd + + Mov [MIDIBuffer+BX], AL + Mov [MIDIBufferTail], BL + +CheckMIDIEnd: + Pop DS + Ret + +EndP CheckMIDI + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ESSIRQHandler + + PushAD + Push DS + Push ES + + ClD + + Mov AX, CS + Mov DS, AX + Assume DS:Driver + +; Inc Debug + +Comment ~ + Mov DX, [ConfigPort] + Add DL, 6 + In AL, DX + Test AL, 8 + JZ ESSNoMIDI + + Push AX + Call CheckMIDI + Pop AX + +ESSNoMIDI: + Test AL, 1 + JZ ESSIRQEnd +~ + Mov DX, [BasePort] ; ESSAck + Add DL, 0Eh ; ESSAck + In AL, DX ; ESSAck + + Mov AL, 20h ; IRQAck + Cmp IRQ, 8 ; IRQAck + JB WSSAckIRQ1 ; IRQAck + ; IRQAck + Out 0A0h, AL ; IRQAck + ; IRQAck +WSSAckIRQ1: ; IRQAck + Out 20h, AL ; IRQAck + +DMAPort1 EQU $+1 + In AL, 1 + Mov BL, AL +DMAPort2 EQU $+1 + In AL, 1 + Mov BH, AL + + Xor AX, AX + + Cmp BX, DMABUFFERLENGTH/2 + JB WSSIRQHandler1 + + Mov AX, DMABUFFERLENGTH/2 + +WSSIRQHandler1: + FNSave [FPSave] + + ; OK... time to get next block + ; Check whether stereo thing is on.. + ; + LES DI, [ActualDMAPtr] + Mov BX, DMASize ; BX = bytes required + Add DI, AX + ShR BX, 1 + ; BX = samples required + Call SaveEMSPageFrame + + Cmp MixTransferRemaining, 0 + JNE ESSIRQHandler4 + Assume DS:Nothing + +ESSIRQHandler3: + Push BX + Push CX + Push BP + Push ES + Push DI + + Call Update + Call MixSamples + + Pop DI + Pop ES + Pop BP + Pop CX + Pop BX + +ESSIRQHandler4: + Mov DS, MixSegment + Mov SI, MixTransferOffset + Mov DX, BX ; DX = samples to transfer + Cmp DX, MixTransferRemaining + JBE ESSIRQHandler5 + + Mov DX, MixTransferRemaining + +ESSIRQHandler5: + +include mmxtrans.inc + + Sub MixTransferRemaining, DX ; } Memory write + Sub BX, DX + JNZ ESSIRQHandler3 + + Mov MixTransferOffset, SI ; } Memory write + + Call RestoreEMSPageFrame + + FNRstor [CS:FPSave] + +ESSIRQEnd: + Pop ES + Pop DS + PopAD + IRet + +EndP ESSIRQHandler + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Add DI, Offset IRQData + Mov BX, [CS:DI] + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset ESSIRQHandler + + XChg [ES:BX], EAX + Mov OldESSIRQHandler, EAX + + Mov AX, IMR + And AX, [DI+2] + + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Pop ES + PopAD + + Ret + +EndP SetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Mov BX, [IRQData+DI] + + Mov EAX, OldESSIRQHandler + Mov [ES:BX], EAX + + Pop ES + PopAD + + Ret + +EndP ResetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetESSMixConst + + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, CmdLineMixSpeed + Mov CX, MixSpeed + Test AX, AX + JZ GetESSMixConst1 + + Mov CX, 22050 + Cmp AX, CX + JB GetESSMixConst1 + + Mov CX, 56821 + Cmp AX, CX + JA GetESSMixConst1 + + Mov CX, AX + +GetESSMixConst1: ; CX = mixspeed. + Mov DX, 0Ch + Mov AX, 236Ch ; DX:AX = 795.5kHz + Div CX + + Mov BX, AX + Neg AL + Mov ESSMixConst, AL + + Mov DX, 0Ch + Mov AX, 236Ch + Div BX + Mov MixSpeed, AX + + FNInit + FILd DWord Ptr [MixSpeed] + FMul FreqMultiplier + FStP FreqMultiplier + + Pop DS + PopA + Ret + +EndP GetESSMixConst + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StartESS + + PushA + Push ES + Push DS + + Push CS + Pop DS + Assume DS:Driver + + ; Setup DMA + Mov BX, MixSegment + Mov AX, 80 + Mov DX, DMA + Mov DI, DMABUFFERLENGTH + Call SetDMA + + LES DI, ActualDMAPtr + Xor AX, AX + Mov CX, DMABUFFERLENGTH/2 + Rep StosW + + Mov MixBufferPos, 0 + Mov MixTransferRemaining, 0 + + Mov AX, BasePort + Call ResetDSP + Mov DX, AX + Add DL, 0Ch + +; Extended Functions + + Mov AL, 0C6h + Call ESSOut + +; Autoinit DMA + + Mov AL, 0B8h + Call ESSOut + Mov AL, 4 + Call ESSOut + +; Stereo/Mono select + + Mov AH, 0A8h + Call ESSReadRegister + Mov AH, AL + Mov AL, 0A8h + Call ESSOut + Mov AL, AH + And AL, Not 3 + Or AL, 2 + Cmp Stereo, 0 + JE StartESS1 + + Xor AL, 3 + +StartESS1: + Call ESSOut + +; DMA mode + + Mov AL, 0B9h + Call ESSOut + Mov AL, 2 + Call ESSOut + +; Mixspeed + + Mov AL, 0A1h + Call ESSOut + Mov AL, ESSMixConst + Call ESSOut + +; Filter clock divider + Mov AL, 0A2h + Call ESSOut + + Mov AL, 0FEh + Call ESSOut + +; DMA counter + Mov CX, DMASize + Neg CX + + Mov AL, 0A4h + Call ESSOut + Mov AL, CL + Call ESSOut + Mov AL, 0A5h + Call ESSOut + Mov AL, CH + Call ESSOut + +; Initialise DAC + Mov AL, 0B6h + Call ESSOut + Mov AL, 0 + Call ESSOut + +; Configure DACs + + Mov AL, 0B7h + Call ESSOut + Mov AL, 71h + Call ESSOut + + Mov AL, 0B7h + Call ESSOut + + Mov AL, 0BCh + Cmp Stereo, 0 + JNE StartESS2 + + Mov AL, 0F4h + +StartESS2: + Call ESSOut + +; IRQ configuration + Mov AH, 0B1h + Call ESSReadRegister + Mov AH, AL + Mov AL, 0B1h + Call ESSOut + Mov AL, AH + And AL, 0Fh + Or AL, 50h + Call ESSOut + +; DMA configuration + Mov AH, 0B2h + Call ESSReadRegister + Mov AH, AL + Mov AL, 0B2h + Call ESSOut + Mov AL, AH + And AL, 0Fh + Or AL, 50h + Call ESSOut + +; Enable voice + Mov AL, 0D1h + Call ESSOut + +; Start transfer + Mov AH, 0B8h + Call ESSReadRegister + Mov AH, AL + Mov AL, 0B8h + Call ESSOut + Mov AL, AH + Or AL, 1 + Call ESSOut + +Comment ~ + +; Init UART + Mov DX, MIDIPort + Inc DX + Mov AL, 3Fh ; Intelligent mode. + Out DX, AL + +; Enable MIDI IRQ + Mov DX, BasePort + Add DL, 4 + Mov AX, 4064h + Out DX, AX + +~ + + Pop DS + Pop ES + PopA + + Ret + +EndP StartESS + Assume DS:Nothing + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov SI, Offset RelocationTable + +RelocationFix: + LodsW + Test AX, AX + JZ RelocationEnd + Mov BX, AX + Mov [BX], DS + Jmp RelocationFix + + +RelocationEnd: + Call GetEMSPageFrame + Mov EMSPageFrame, AX + + In AL, 0A1h + Mov AH, AL + In AL, 21h + Mov IMR, AX + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + Mov DX, BasePort + Add DL, 4 + Mov AL, 22h + Out DX, AL + Inc DX + In AL, DX + Mov AH, AL + And AX, 0FF0h + ShR AH, 1 + ShR AL, 5 + Mov Word Ptr [VolumeTable], AX + + Call GetESSMixConst + + Mov AX, 2643 + Mul MixSpeed + Add AX, 0FFFFh + AdC DX, (DMABUFFERLENGTH*2)/16 + 5 + Mov BX, DX + + ; Allocate MixSegment first + Mov AH, 48h + + Int 21h + JNC InitSound1 + +InitSoundNoMemory: + Mov SI, Offset ESSNoMemoryMsg + Ret + +InitSound1: + Mov MixSegment, AX + + Call SetIRQ + Call GetTempo + Call SetTempo + + Mov SI, Offset ESSMsg + + Mov AX, BasePort + Mov BX, IRQ + Mov CX, DMA + + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Call ResetIRQ + Call SetIRQ + + Mov SI, Offset ReInitMsg + Mov BX, 40 + Call SetInfoLine + + Mov AL, Stereo + Call SetStereo + + Pop ES + Pop DS + PopA + + Ret + +EndP ReInitSound + Assume DS:Nothing + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, IMR + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Mov AX, MixSegment + Test AX, AX + JZ UnInitSound1 + + Mov ES, AX + Mov AH, 49h ; Release MixSegment + Int 21h + + Mov AX, BasePort + Call ResetDSP + Call ResetIRQ + +UnInitSound1: + Ret + +EndP UnInitSound + Assume DS:Nothing + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + Push CS + Pop DS + Assume DS:Driver +; +;DMAPort1 EQU $+1 +; In AL, 1 +; Mov BL, AL +;DMAPort2 EQU $+1 +; In AL, 1 +; Mov BH, AL +; +; Mov Debug2, BX + +Poll1: + Call [UARTBufferEmpty] + JNC PollEnd + + Xor BX, BX + + ClI + + Mov BL, MIDIBufferHead + Cmp BL, MIDIBufferTail + JZ PollEnd ; Nothing in queue + + Inc BL + Mov AL, [MIDIBuffer+BX] + Mov MIDIBufferHead, BL + + Call [UARTSend] + Jmp Poll1 + +PollEnd: + StI + + Ret + +EndP Poll + Assume DS:Nothing + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Push AX + Push BX + Push DX + + Push BX + + Mov AX, MixSpeed + Mov BX, AX + Xor DX, DX + + ShL AX, 1 + RCL DX, 1 ; DX:AX = Mixspeed*2 + + ShR BX, 1 ; BX = Mixspeed/2 + + Add AX, BX + AdC DX, 0 ; DX:AX = Mixspeed*2.5 + + Pop BX ; BX = tempo + Div BX + + Mov BytesToMix, AX + + Pop DX + Pop BX + Pop AX + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + Mov CS:MixVolume, AX + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Jmp CS:RecalculateAllVolumes + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Mov CS:Stereo, AL + Cmp CS:MixSegment, 0 + JE SetStereo1 + + Mov AX, BasePort + Call ResetDSP + Call StartESS + +SetStereo1: + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include loadsam.inc + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset ESSScreenList + + ClC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far + + Xor AH, AH + Mov AL, [CS:VolumeTable+DI] + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far + + Push DS + Push DX + + Push CS + Pop DS + Assume DS:Driver + + Mov [VolumeTable+DI], AL + + Mov DX, BasePort + Add DL, 4 + Mov AL, 22h + Out DX, AL + Mov AH, [VolumeTable] + ShL AH, 4 + Or AH, [VolumeTable+1] + ShL AH, 1 + Out DX, AX + + Pop DX + Pop DS + Ret + +EndP SetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +InterpretState DB 0 +InterpretType DB 0 + +Proc SendUARTOut Far ; Local interpreter activated with 0F0h 0F0h. + + Mov AH, CS:InterpretState + Cmp AH, 2 + JB SendUARTOut1 + +; In interpreter. + JE SendUARTOut3 + +; Have InterpretType, now get parameter, then return to normal. + + Cmp AL, 7Fh + JA SendUARTOut4 + + Push BX + + Mov BL, CS:InterpretType ; Want BX = InterpretType*64+Channel + ; + ShL BX, 6 + Add BL, [DI+20h] + And BX, 127 + Mov [CS:FilterParameters+BX], AL + + Pop BX + + Test SI, SI + JZ SendUARTOut4 + + Or Byte Ptr [SI], 64 + +SendUARTOut4: + Mov CS:InterpretState, 0 + Ret + +SendUARTOut3: + Cmp AL, 2 + JAE SendUARTOut4 + + Mov CS:InterpretType, AL + Jmp SendUARTOutStateInc + +SendUARTOut1: + Cmp AL, 0F0h + JNE SendUARTOut2 + +SendUARTOutStateInc: + Inc CS:InterpretState + Ret + +SendUARTOut2: + Test AH, AH + JZ SendUARTOutEnd + + Push AX + Mov AL, 0F0h +; Call UARTOut + Pop AX + Mov CS:InterpretState, 0 + +SendUARTOutEnd: + Cmp AL, 0FCh + JE ResetFilters + Cmp AL, 0FAh + JE ResetFilters + + Cmp AL, 0FFh + JNE SendUARTOutNoClear + +ResetFilters: + PushA + Push ES + + Push CS + Pop ES + + Mov DI, Offset FilterParameters + Mov CX, 64 + Mov AL, 7Fh + Rep StosB + Mov CX, 64 + Xor AX, AX + Rep StosB + + Pop ES + PopA + +SendUARTOutNoClear: +; Call UARTOut + Ret + +EndP SendUARTOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. + +StopAfterPlay DW 0 +DefaultChannels DW 128 + DW 3 + DW 4 Dup (0) + + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + DW Offset SendUARTOut + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/ES1868.ASM b/SoundDrivers/ES1868.ASM new file mode 100755 index 0000000..ab64c5f --- /dev/null +++ b/SoundDrivers/ES1868.ASM @@ -0,0 +1,2328 @@ +; +; ESS Technology's ES1868 AudioDrive chip. +; + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;********************************** + +PNPSERIALID EQU 0FFFFFFFFh +PNPVENDORID EQU 68187316h + +STEREOENABLED EQU 1 +DMABUFFERLENGTH EQU 8192 +MIXRESOLUTION EQU 32 ; 32 bit mixing for +MIXTABLESIZE EQU 2*256*65 + +ESSMsg DB "ESS ES1868 AudioDrive found", 13 + DB "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, DMA ", 0FDh, "D", 0 + +ESSNoMemoryMsg DB "ESS ES1868 AudioDrive found", 13 + DB "Error: Insufficient memory", 0 + +ReinitMsg DB "ESS ES1868 AudioDrive reinitialised", 0 + +ConfigErrorMsg DB "Error saving configuration to ITES1868.DRV", 0 +ConfigOKMsg DB "Configuration saved to ITES1868.DRV", 0 + +DriverName DB "ITES1868.DRV", 0 + +ALIGN 4 +FilterValue DD 0 +FilterValue2 DD 0 +ESSMixConst DB 0, 0 + +DMASize DW 2048 ; Smaller gives better MIDI timing +ConfigPort DW 0 + +Forced DB 0 +Stereo DB 0 +MixVolume DW 0 + +BytesToMix DW 1000 + +MixSegment DW 0 +DMASegment DW 0 + +MixTransferOffset DW 0 +MixTransferRemaining DW 0 + +CONFIGURATIONOFFSET EQU $+128 +CONFIGSIZE EQU 6 +MixMode DW 0 +MixModeOffset DW 0 +Filter DW 0 + +IMR DW 0 +OldESSIRQHandler DD 0 + +IRQData Label Word + DW 20h, 1111111111111110b ; IRQ 0 + DW 24h, 1111111111111101b ; IRQ 1 + DW 28h, 1111110111111011b ; IRQ 2 + DW 2Ch, 1111111111110111b ; IRQ 3 + DW 30h, 1111111111101111b ; IRQ 4 + DW 34h, 1111111111011111b ; IRQ 5 + DW 38h, 1111111110111111b ; IRQ 6 + DW 3Ch, 1111111101111111b ; IRQ 7 + DW 1C0h, 1111111011111011b ; IRQ 8 + DW 1C4h, 1111110111111011b ; IRQ 9 + DW 1C8h, 1111101111111011b ; IRQ 10 + DW 1CCh, 1111011111111011b ; IRQ 11 + DW 1D0h, 1110111111111011b ; IRQ 12 + DW 1D4h, 1101111111111011b ; IRQ 13 + DW 1D8h, 1011111111111011b ; IRQ 14 + DW 1DCh, 0111111111111011b ; IRQ 15 + +ESSScreenList Label + DW 6 + DW Near Ptr IdleFunctionList + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr ESSHeaderLine + + DW Near Ptr DriverText + + DW Near Ptr MixModeText + DW Near Ptr MixModeButton1 ; 6 + DW Near Ptr MixModeButton2 ; + DW Near Ptr MixModeButton3 ; 8 + DW Near Ptr MixModeButton4 ; 9 + + DW Near Ptr FilterText + DW Near Ptr FilterButton1 ; 11 + DW Near Ptr FilterButton2 + DW Near Ptr FilterButton3 + +Comment ~ + + DW Near Ptr VolumeText + DW Near Ptr VolumeBox1 + + DW Near Ptr MasterVolumeLeft ; 16 + DW Near Ptr MasterVolumeRight ; 17 + +~ + + DW 0 + +ESSHeaderLine DW 10 + DB "ESS ES1868 AudioDrive Driver", 0 + +EmptyObject DW 1 + DB 0, 0 + DB 0 + DB 0 + +DriverText DW 1 + DB 26, 48 + DB 21h + DB "ESS ES1868 AudioDrive Driver 1.0 for Impulse Tracker", 0 + +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +IdleFunctionList DD 0 + DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +Comment ~ + +VolumeText DW 1 + DB 2, 14 + DB 20h + DB "Master Volume Left", 13 + DB "Master Volume Right" + DB 0 + +VolumeBox1 DW 0 + DB 21, 13, 31, 16 + DB 25 + +MasterVolumeLeft DW 14 + DB 22, 14 + DW 0, 15 + DW 9, 0 + DW 0FFFFh, 17, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 8 + +MasterVolumeRight DW 14 + DB 22, 15 + DW 0, 15 + DW 9, 1 + DW 16, 6, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 8 + +~ + +MixModeText DW 1 + DB 2, 14 + DB 20h + DB "Mixing Mode, Playback Frequency: ", 0FDh, "DHz", 0 +MixSpeed DW 44100 + +MixModeButton1 DW 2 + DW 0FFFFh, 7, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment1 DW 0 + DW 0 + DW Offset SetMixMode +DriverSegment2 DW 0 + DB 3, 16, 32, 18, 8 + DB 0 + DB " 16 Bit, Non-Interpolated", 0 + +MixModeButton2 DW 2 + DW 6, 8, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment3 DW 0 + DW 2 + DW Offset SetMixMode +DriverSegment4 DW 0 + DB 3, 19, 32, 21, 8 + DB 0 + DB " 16 Bit, Interpolated", 0 + +MixModeButton3 DW 2 + DW 7, 9, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment5 DW 0 + DW 4 + DW Offset SetMixMode +DriverSegment6 DW 0 + DB 3, 22, 32, 24, 8 + DB 0 + DB " 32 Bit, Non-Interpolated", 0 + +MixModeButton4 DW 2 + DW 8, 11, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment7 DW 0 + DW 6 + DW Offset SetMixMode +DriverSegment8 DW 0 + DB 3, 25, 32, 27, 8 + DB 0 + DB " 32 Bit, Interpolated", 0 + +FilterText DW 1 + DB 2, 29 + DB 20h + DB "Filter mode", 0 + +FilterButton1 DW 2 + DW 9, 12, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment9 DW 0 + DW 0 + DW Offset SetFilter +DriverSegment10 DW 0 + DB 3, 31, 29, 33, 8 + DB 0 + DB " No Filter", 0 + +FilterButton2 DW 2 + DW 11, 13, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment11 DW 0 + DW 1 + DW Offset SetFilter +DriverSegment12 DW 0 + DB 3, 34, 29, 36, 8 + DB 0 + DB " 50% Filter", 0 + +FilterButton3 DW 2 + DW 12, 0FFFFh, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment13 DW 0 + DW 2 + DW Offset SetFilter +DriverSegment14 DW 0 + DB 3, 37, 29, 39, 8 + DB 0 + DB " 75% Filter", 0 + +ALIGN 4 + +VolumeTable DB 2 Dup (0) +MIDIPort DW 0 + +MIDIBuffer DB 256 Dup (0) +MIDIBufferHead DB 0 +MIDIBufferTail DB 0 + +; ÄÄ MixingRoutines ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixBufferPos DW 0 + +include dma.inc +include mix.inc +include m12bit.mix +include m12biti.mix +include m32bit.mix +include m32biti.mix + +MixFunctionTables Label + +include m12bit.inc ; contains the tables +include m12biti.inc +include m32bit.inc +include m32biti.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +RelocationTable Label Word + DW Offset DriverSegment1, Offset DriverSegment2 + DW Offset DriverSegment3, Offset DriverSegment4 + DW Offset DriverSegment5, Offset DriverSegment6 + DW Offset DriverSegment7, Offset DriverSegment8 + DW Offset DriverSegment9, Offset DriverSegment10 + DW Offset DriverSegment11, Offset DriverSegment12 + DW Offset DriverSegment13, Offset DriverSegment14 + DW 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ESSOut ; AL = data + ; DX = 2xCh + + Push AX + +ESSOut1: + In AL, DX + Test AL, AL + JS ESSOut1 + + Pop AX + Out DX, AL + + Ret + +EndP ESSOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ESSIn ; DX = 2xCh, returns AL + +ESSIn1: + In AL, DX + Test AL, 40h + JZ ESSIn1 + + Add DL, 0Ah-0Ch ; DX = 2xAh -> Data read port + In AL, DX + Add DL, 0Ch-0Ah + + Ret + +EndP ESSIn + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UARTOut ; AL = out + + Push DX + Push AX + + Mov DX, CS:MIDIPort + Inc DX + +UARTOut1: + In AL, DX + Test AL, 40h + JNZ UARTOut1 + + Pop AX + Dec DX + Out DX, AL + + Pop DX + Ret + +EndP UARTOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UARTIn ; returns AL + + Push DX + + Mov DX, CS:MIDIPort + Inc DX + +UARTIn1: + In AL, DX + Test AL, 80h + JNZ UARTIn1 + + Dec DX + In AL, DX + + Pop DX + Ret + +EndP UARTIn + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ESSReadRegister ; AH = register to read. + ; DX = 2xCh + ; returns AL + + Mov AL, 0C0h + Call ESSOut + Mov AL, AH + Call ESSOut + Call ESSIn + + Ret + +EndP ESSReadRegister + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixMode Far + + Push CS + Pop ES + Mov DI, Offset MixMode + + Ret + +EndP GetMixMode + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetFilter Far + + Push CS + Pop ES + Mov DI, Offset Filter + + Ret + +EndP GetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetFilter Far + + Mov AX, [SI+22] + Mov CS:FilterValue, 0 + Mov CS:Filter, AX + ClI + Jmp SetMixModeChain + +EndP SetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixMode Far + + Mov AX, [SI+22] + + ClI + + Mov CS:MixMode, AX + + Mov BX, 180 + Mul BX + Mov CS:MixModeOffset, AX + + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS:RecalculateAllVolumes + + StI + +SetMixModeChain: + Call GotoHomeDirectory + + ; Now to save config into driver file. + Push CS + Pop DS + Assume DS:Driver + + Mov AX, 3D02h ; Read write access + Mov DX, Offset DriverName + Mov SI, Offset ConfigErrorMsg + Int 21h + JC SetMixMode1 + + Mov BX, AX + + Mov AX, 4200h + Xor CX, CX + Mov DX, Offset CONFIGURATIONOFFSET + Int 21h + JC SetMixMode2 + + Mov AH, 40h + Mov CX, CONFIGSIZE + Mov DX, Offset MixMode + Int 21h + +SetMixMode2: + PushF + Mov AH, 3Eh + Int 21h + PopF + + JC SetMixMode1 + + Mov SI, Offset ConfigOKMsg + +SetMixMode1: + Mov BX, 40 + Call SetInfoLine + + Mov AX, 1 + Ret + +EndP SetMixMode + Assume DS:Nothing + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +PnP_SerialID DD 0 +PnP_VendorID DD 0 +PnP_ReadPort DW 0 +PnP_CSN DB 0 +PnP_CardFound DB 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_Delay + Assume DS:Driver + + Push AX CX + + Mov CX, 180h +PnP_Delay1: + In AL, 21h + Loop PnP_Delay1 + + Pop CX AX + Ret + +EndP PnP_Delay + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_WriteData + + Mov DX, 279h + Out DX, AL + + Mov AL, AH + Mov DH, 0Ah + Out DX, AL + Ret + +EndP PnP_WriteData + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_ReadData + + Mov DX, 279h + Out DX, AL + + Mov DX, PnP_ReadPort + In AL, DX + + Ret + +EndP PnP_ReadData + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_Isolate + + Mov AX, 402h + Call Pnp_WriteData ; Reset CSNs + +PnP_IsolateNextCard: + Mov AX, 0003h + Call PnP_WriteData ; Wake[0] + + Mov AX, PnP_ReadPort + ShL AX, 6 + Xor AL, AL + Call PnP_WriteData ; Set Read Data port. + + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + + Mov AL, 1 ; Serial Isolation + Mov DX, 279h + Out DX, AL + + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + + Mov BL, 6Ah + Mov CX, 64 + Mov DX, PnP_ReadPort + + ClI + +PnP_Isolate1: + ShR PnP_SerialID, 1 + RCR PnP_VendorID, 1 + + Mov BH, BL + ShR BH, 1 + Xor BH, BL + ShR BX, 1 + + In AL, DX + Mov AH, AL + Call PnP_Delay + In AL, DX + Call PnP_Delay + + Cmp AX, 55AAh + JNE PnP_Isolate2 + + Xor BL, 80h + Or PnP_SerialID, 80000000h + +PnP_Isolate2: + Dec CX + JNZ PnP_Isolate1 + + Mov CX, 8 + Xor BH, BH + +PnP_Isolate3: + ShR BH, 1 + + In AL, DX + Mov AH, AL + Call PnP_Delay + In AL, DX + Call PnP_Delay + Cmp AX, 55AAh + JNE PnP_Isolate4 + + Or BH, 80h + +PnP_Isolate4: + Dec CX + JNZ PnP_Isolate3 + + StI + + Cmp BL, BH ; Matching Checksum? + JNE PnP_IsolateFinished + + ; assign CSN + Inc PnP_CSN + + Mov AL, 6 + MOv AH, PnP_CSN + Call PnP_WriteData + +; Cmp PnP_VendorID, PNPVENDORID +; JNE PnP_IsolateNextCard + Cmp PnP_SerialID, PNPSERIALID + JNE PnP_IsolateNextCard + + Mov AL, 3 + Call PnP_WriteData + + Mov AX, 07h ; Configuration device + Call PnP_WriteData + + Mov AL, 60h + Call PnP_ReadData + Mov AH, AL + Mov AL, 61h + Call PnP_ReadData ; AX = address. + Mov ConfigPort, AX + + Mov AX, 107h ; Audio device + Call PnP_WriteData + + Mov AL, 64h + Call PnP_ReadData + Mov AH, AL + Mov AL, 65h + Call PnP_ReadData ; AX = address. + Mov MIDIPort, AX + + Mov AL, 60h + Call PnP_ReadData + Mov AH, AL + Mov AL, 61h + Call PnP_ReadData ; AX = address. + Cmp BasePort, 0FFFFh + JE PnPBasePortOK + + Cmp BasePort, AX + JNE PnP_IsolateNextCard + +PnPBasePortOK: + Mov BasePort, AX + + Mov AL, 70h + Call PnP_ReadData ; AL[3:0] = IRQ + And AX, 15 + JZ PnP_IsolateNextCard + Mov IRQ, AX + + Mov AL, 74h + Call PnP_ReadData ; AL[2:0] = DMA + And AX, 7 + Cmp AL, 4 + JE PnP_IsolateNextCard + Mov DMA, AX + + Mov Pnp_CardFound, 1 + Jmp PnP_IsolateNextCard + +PnP_IsolateFinished: + Mov AL, PnP_CSN + ShL AL, 1 + Or AL, PnP_CardFound + + Ret + +EndP PnP_Isolate + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far ; returns carry clear if succesful + + Push CS + Pop DS + + Xor AL, AL + Mov DX, 279h + Out DX, AL + Out DX, AL + + Mov AL, 6Ah ; Starting value + Mov CX, 32 + +PnP_InitiationKeyLoop: + Out DX, AL + + Mov AH, AL + ShR AH, 1 + Xor AH, AL + ShR AX, 1 + + Dec CX + JNZ PnP_InitiationKeyLoop + +; Try three ports before concluding no PnP cards: 20Fh, 27Bh, 213h + +PnP_DetectCardPort1: + Mov PnP_ReadPort, 20Fh + Call PnP_Isolate + JZ PnP_DetectCardPort2 + Test AL, 1 + JZ PnP_DetectCardNotFound + Jmp PnP_DetectCardFound + +PnP_DetectCardPort2: + Mov PnP_ReadPort, 27Bh + Call PnP_Isolate + JZ PnP_DetectCardPort3 + Test AL, 1 + JZ PnP_DetectCardNotFound + Jmp PnP_DetectCardFound + +PnP_DetectCardPort3: + Mov PnP_ReadPort, 213h + Call PnP_Isolate + Test AL, 1 + JNZ PnP_DetectCardFound + +PnP_DetectCardNotFound: + StC + Jmp PnP_DetectEnd + +PnP_DetectCardFound: + ClC + +PnP_DetectEnd: ; Return PnP to wait for key state + Mov AX, 202h + Call PnP_WriteData + Mov EAX, 'Jeff' + + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetDSP Far ; AX = Port + + Push AX + Push CX + Push DX + + Mov DX, CS:MIDIPort + Inc DX + Mov AL, 0FFh + Out DX, AL + + Mov DX, CS:BasePort + Add DL, 6 + Mov AL, 3 + Out DX, AL + + In AL, DX + In AL, DX + In AL, DX + In AL, DX + + Xor AL, AL + Out DX, AL + + Add DL, 8 + Mov CX, 200 + +ResetDSP1: + In AL, DX + Test AL, AL + JS ResetDSP2 + Loop ResetDSP1 + Jmp ResetDSP3 + +ResetDSP2: + Sub DL, 4 + In AL, DX + Cmp AL, 0AAh + JE ResetDSP4 + Add DL, 4 + Loop ResetDSP1 + +ResetDSP3: + StC + +ResetDSP4: + Pop DX + Pop CX + Pop AX + Ret + +EndP ResetDSP + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixModeTable Label Word + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + +Proc MixSamples ; Given DS:SI = info tables, CX = numchannels + + ; 1. Clean buffer + ; + update variables + ; 2. Update parameters + ; 3. Mix func + ; 4. Return + + Push CX + + Mov CX, BytesToMix + Mov ES, MixSegment + Mov DI, MIXTABLESIZE + Xor EAX, EAX + Mov DX, CX + Add CX, CX + + Mov MixTransferOffset, DI ; } Memory write + + Cmp Stereo, 0 + JE MixSamples1 + + Mov DX, CX + +MixSamples1: + Rep StosD ; } Memory write + Mov MixTransferRemaining, DX ; } + + Pop CX + +MixSamples2: + Test Byte Ptr [SI], 1 + JZ MixSamplesEnd2 + Cmp Byte Ptr [SI+36h], 100 + JE MixSamplesEnd2 + + Push CX + Mov CX, [SI] + + Test CH, 2 + JZ MixSamples3 + And Byte Ptr [SI], Not 1 + + Jmp MixSamplesEnd +; Cmp MixMode, 8 ; Is it volume ramping? +; JB MixSamplesEnd + +MixSamples3: + Test CL, 20h ; New freq? + JZ MixSamples5 + + Mov AX, [SI+10h] + Mov DX, [SI+12h] + Mov BX, MixSpeed + Cmp DX, BX + JAE MixSamplesHandleError + + Div BX + ShL EAX, 16 + Xor AX, AX + Div BX + Mov STEPVALUE, EAX + +MixSamples4: + Test CH, 1 + JZ MixSamples5 + + Mov DWord Ptr [SI+1Ch], 0 ; Current Volume = 0 + ; for volume sliding. +MixSamples5: + Test CX, 8440h ; New volume or panning? + JZ MixSamplesMix + + Xor AX, AX + Test CH, 8 ; Muted? + JNZ MixModeCommon + + Mov BX, MixMode + Add BL, Stereo + Add BX, BX + Jmp [CS:MixModeTable+BX] + +Mix0Mode: ; 16-bit mixing, no interpolation +Mix0ModeMono: ; and 16-bit mixing, interpolation + Mov AL, [SI+20h] + ShR AL, 1 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 30 ; Use left only-mixing for mono + Jmp MixModeCommon + +Mix0ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix0ModeSurround + + Mul Byte Ptr [SI+20h] ; Final volume + Add AX, 64 + ShR AX, 7 + Mov [SI+0Ch], AX ; Store into right volume + + Mov AL, 64 + Sub AL, [SI+37h] + Mul Byte Ptr [SI+20h] + Add AX, 64 + ShR AX, 7 + Mov [SI+0Eh], AX ; Left volume + + Mov CH, AL ; CH = left volume + Mov CL, [SI+0Ch] ; CL = right volume + Mov AX, 0 + + Test CX, CX + JZ MixModeCommon + + Mov AL, 30 ; Left only... + Test CL, CL + JZ MixModeCommon + + Mov AL, 60 + Test CH, CH + JZ MixModeCommon + + Mov AL, 90 + Cmp CL, CH + JZ MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix0ModeSurround: + Mov AL, [SI+20h] + ShR AL, 2 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 150 ; Surround + Jmp MixModeCommon + +Mix6ModeMono: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 8 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Test AX, AX + JZ MixModeCommon + Mov AX, 30 + Jmp MixModeCommon + +Mix6ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix6ModeSurround + + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Ch], AX ; Store into right volume + Mov BX, AX + ShL EAX, 16 + + Mov AL, 64 ; Do left volume + Sub AL, [SI+37h] ; AL = 64-FinalPan + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Eh], AX + + Mov ECX, EAX + + ; BX = right volume + ; CX = Left volume + Mov AX, 0 + Test ECX, ECX + JZ MixModeCommon + + Mov AL, 30 + Test BX, BX + JZ MixModeCommon + + Mov AL, 60 + Test CX, CX + JZ MixModeCommon + + Mov AL, 90 + Cmp CX, BX + JE MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix6ModeSurround: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 9 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + JZ MixModeCommon + Mov AX, 150 + Jmp MixModeCommon + +MixModeCommon: ; Requires AX = 30/60/90 etc. depending + ; On mixing mode type. + ; This will add 180 for 16-bit, + ; And sort out loop types. + Mov BL, [SI+0Ah] + Test Byte Ptr [SI+18h], 2 ; 16 bit? + JZ MixModeCommon1 + + Add AX, 180 + +MixModeCommon1: + Cmp BL, 8 + JB MixModeCommon3 ; No loop + JE MixModeCommon2 ; Forwards loop + + Add AX, 10 + +MixModeCommon2: + Add AX, 10 + +MixModeCommon3: + Add AX, Offset MixFunctionTables + Add AX, MixModeOffset + Mov [SI+8], AX ; Offset... + +MixSamplesMix: + Mov BX, [SI+8] ; BX = offset into + Mov EAX, [CS:BX+2] + Mov DWord Ptr PreMixFunction, EAX + Mov EAX, [CS:BX+6] + Mov DWord Ptr MixFunctionSeparateBackwards, EAX + + Mov AX, BytesToMix + Mov MixBlockSize, AX + Mov MixBufferOffset, MIXTABLESIZE + + Mov EAX, CURRENTPOSITION + Mov OLDPOSITION, EAX + + Call Word Ptr [CS:BX] + + And Word Ptr [SI], 0111100010001101b + Jmp MixSamplesEnd + +MixSamplesHandleError: + Mov Word Ptr [SI], 200h + + Test Byte Ptr [SI+3Ah], 80h + JNZ MixSamplesEnd + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Turn off channel + +MixSamplesEnd: + Pop CX + +MixSamplesEnd2: + Add SI, 128 + Dec CX + JNZ MixSamples2 + + Ret + +EndP MixSamples + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc CheckMIDI + + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Xor BX, BX + Call UARTIn + Mov BL, [MIDIBufferTail] + + Cmp AL, 0F0h + JAE CheckMIDIEnd + + Inc BL + Cmp BL, MIDIBufferHead + JE CheckMIDIEnd + + Mov [MIDIBuffer+BX], AL + Mov [MIDIBufferTail], BL + +CheckMIDIEnd: + Pop DS + Ret + +EndP CheckMIDI + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ESSIRQHandler + + PushAD + Push DS + Push ES + + ClD + + Mov AX, CS + Mov DS, AX + Assume DS:Driver + + Mov DX, [ConfigPort] + Add DL, 6 + In AL, DX + Test AL, 8 + JZ ESSNoMIDI + + Push AX + Call CheckMIDI + Pop AX + +ESSNoMIDI: + Test AL, 1 + JZ ESSIRQEnd + + Mov DX, [BasePort] + Add DL, 0Eh + In AL, DX + + Mov AX, MixBufferPos + Mov BX, AX + Mul DMASize + Cmp AX, DMABUFFERLENGTH + JB ESSIRQHandler2 + + Xor AX, AX + Xor BX, BX + +ESSIRQHandler2: + Inc BX + Mov MixBufferPos, BX + + CLD + + + ; OK... time to get next block + ; Check whether stereo thing is on.. + ; + LES DI, [ActualDMAPtr] + Add DI, AX + + Mov BX, DMASize ; BX = bytes required + ShR BX, 1 + ; BX = samples required + Mov BP, 8 ; Skip for mono + Mov CL, 14 ; Shift for mono + + Cmp Stereo, 0 + JE ESSIRQHandlerMono + + Mov BP, 4 ; Stereo skip value. + Dec CL + +ESSIRQHandlerMono: + Call SaveEMSPageFrame + + Cmp MixTransferRemaining, 0 + JNE ESSIRQHandler4 + Assume DS:Nothing + +ESSIRQHandler3: + Push BX + Push CX + Push BP + Push ES + Push DI + + Call Update + Call MixSamples + + Pop DI + Pop ES + Pop BP + Pop CX + Pop BX + +ESSIRQHandler4: + Mov DS, MixSegment + Mov SI, MixTransferOffset + Mov DX, BX ; DX = samples to transfer + Cmp DX, MixTransferRemaining + JBE ESSIRQHandler5 + + Mov DX, MixTransferRemaining + +ESSIRQHandler5: + Push DX + Cmp CS:Filter, 1 + JB ESSIRQHandler6 + JE ESSIRQHFilter + + Cmp CS:Stereo, 0 + JE ESSIRQ3QFilterMono + +ESSIRQ3QFilterStereo: + Push BX + + Mov EBX, FilterValue + Mov EBP, FilterValue2 + ShR DX, 1 + +ESSIRQ3QFilterStereo1: + Mov EAX, EBX + Mov ECX, EBP + Add EAX, [SI] + Add ECX, [SI+4] + SAR EAX, 1 + SAR ECX, 1 + Add EBX, EAX + Add EBP, ECX + SAR EBX, 1 + SAR EBP, 1 + + Mov EAX, EBX + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSS3QFilterStereoClip1 + Cmp EAX, 7FFFh + JG WSS3QFilterStereoClip2 + +ESSIRQ3QFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSS3QFilterStereoClip3 + Cmp EAX, 7FFFh + JG WSS3QFilterStereoClip4 + +ESSIRQ3QFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ ESSIRQ3QFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp WSSMixTransferEnd + +ESSIRQ3QFilterMono: + Push BX + + Mov EBX, FilterValue + +ESSIRQ3QFilterMono1: + Mov EAX, EBX + Add EAX, [SI] + SAR EAX, 1 + Add EBX, EAX + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL WSS3QFilterMonoClip1 + Cmp EAX, 7FFFh + JG WSS3QFilterMonoClip2 + +ESSIRQ3QFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ ESSIRQ3QFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp WSSMixTransferEnd + +ESSIRQHFilter: + Cmp CS:Stereo, 0 + JE ESSIRQHFilterMono + +ESSIRQHFilterStereo: + Push BX + + Mov EBX, FilterValue + Mov EBP, FilterValue2 + ShR DX, 1 + +ESSIRQHFilterStereo1: + Add EBX, [SI] + Add EBP, [SI+4] + + SAR EBX, 1 + SAR EBP, 1 + + Mov EAX, EBX + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSSHFilterStereoClip1 + Cmp EAX, 7FFFh + JG WSSHFilterStereoClip2 + +ESSIRQHFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSSHFilterStereoClip3 + Cmp EAX, 7FFFh + JG WSSHFilterStereoClip4 + +ESSIRQHFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ ESSIRQHFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp WSSMixTransferEnd + +ESSIRQHFilterMono: + Push BX + + Mov EBX, FilterValue + +ESSIRQHFilterMono1: + Add EBX, [SI] + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL WSSHFilterMonoClip1 + Cmp EAX, 7FFFh + JG WSSHFilterMonoClip2 + +ESSIRQHFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ ESSIRQHFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp WSSMixTransferEnd + +ESSIRQHandler6: + Mov EAX, [SI] + SAR EAX, CL + + Cmp EAX, -8000h + JL ESSIRQHandlerClip1 + Cmp EAX, 7FFFh + JG ESSIRQHandlerClip2 + +ESSIRQHandler7: + StosW ; } Memory write + + Add SI, BP + Dec DX + JNZ ESSIRQHandler6 + +WSSMixTransferEnd: + Pop DX + + Sub MixTransferRemaining, DX ; } Memory write + Sub BX, DX + JNZ ESSIRQHandler3 + + Mov MixTransferOffset, SI ; } Memory write + + Call RestoreEMSPageFrame + +ESSIRQEnd: + Mov AL, 20h + Cmp IRQ, 8 + JB WSSAckIRQ1 + + Out 0A0h, AL + +WSSAckIRQ1: + Out 20h, AL + + Pop ES + Pop DS + PopAD + IRet + +ESSIRQHandlerClip1: + Mov AX, 8000h + Jmp ESSIRQHandler7 + +ESSIRQHandlerClip2: + Mov AX, 7FFFh + Jmp ESSIRQHandler7 + +WSSHFilterMonoClip1: + Mov AX, 8000h + Jmp ESSIRQHFilterMono2 + +WSSHFilterMonoClip2: + Mov AX, 7FFFh + Jmp ESSIRQHFilterMono2 + +WSSHFilterStereoClip1: + Mov AX, 8000h + Jmp ESSIRQHFilterStereo2 + +WSSHFilterStereoClip2: + Mov AX, 7FFFh + Jmp ESSIRQHFilterStereo2 + +WSSHFilterStereoClip3: + Mov AX, 8000h + Jmp ESSIRQHFilterStereo3 + +WSSHFilterStereoClip4: + Mov AX, 7FFFh + Jmp ESSIRQHFilterStereo3 + +WSS3QFilterMonoClip1: + Mov AX, 8000h + Jmp ESSIRQ3QFilterMono2 + +WSS3QFilterMonoClip2: + Mov AX, 7FFFh + Jmp ESSIRQ3QFilterMono2 + +WSS3QFilterStereoClip1: + Mov AX, 8000h + Jmp ESSIRQ3QFilterStereo2 + +WSS3QFilterStereoClip2: + Mov AX, 7FFFh + Jmp ESSIRQ3QFilterStereo2 + +WSS3QFilterStereoClip3: + Mov AX, 8000h + Jmp ESSIRQ3QFilterStereo3 + +WSS3QFilterStereoClip4: + Mov AX, 7FFFh + Jmp ESSIRQ3QFilterStereo3 + +EndP ESSIRQHandler + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Add DI, Offset IRQData + Mov BX, [CS:DI] + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset ESSIRQHandler + + XChg [ES:BX], EAX + Mov OldESSIRQHandler, EAX + + Mov AX, IMR + And AX, [DI+2] + + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Pop ES + PopAD + + Ret + +EndP SetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Mov BX, [IRQData+DI] + + Mov EAX, OldESSIRQHandler + Mov [ES:BX], EAX + + Pop ES + PopAD + + Ret + +EndP ResetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetESSMixConst + + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, CmdLineMixSpeed + Mov CX, MixSpeed + Test AX, AX + JZ GetESSMixConst1 + + Mov CX, 22050 + Cmp AX, CX + JB GetESSMixConst1 + + Mov CX, 56821 + Cmp AX, CX + JA GetESSMixConst1 + + Mov CX, AX + +GetESSMixConst1: ; CX = mixspeed. + Mov DX, 0Ch + Mov AX, 236Ch ; DX:AX = 795.5kHz + Div CX + + Mov BX, AX + Neg AL + Mov ESSMixConst, AL + + Mov DX, 0Ch + Mov AX, 236Ch + Div BX + Mov MixSpeed, AX + + Pop DS + PopA + Ret + +EndP GetESSMixConst + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StartESS + + PushA + Push ES + Push DS + + Push CS + Pop DS + Assume DS:Driver + + ; Setup DMA + Mov BX, DMASegment + Xor AX, AX + Mov DX, DMA + Mov DI, DMABUFFERLENGTH + Call SetDMA + + LES DI, ActualDMAPtr + Xor AX, AX + Mov CX, DMABUFFERLENGTH/2 + Rep StosW + + Mov MixBufferPos, 0 + Mov MixTransferRemaining, 0 + + Call ResetDSP + Mov DX, BasePort + Add DL, 0Ch + +; Extended Functions + + Mov AL, 0C6h + Call ESSOut + +; Autoinit DMA + + Mov AL, 0B8h + Call ESSOut + Mov AL, 4 + Call ESSOut + +; Stereo/Mono select + + Mov AH, 0A8h + Call ESSReadRegister + Mov AH, AL + Mov AL, 0A8h + Call ESSOut + Mov AL, AH + And AL, Not 3 + Or AL, 2 + Cmp Stereo, 0 + JE StartESS1 + + Xor AL, 3 + +StartESS1: + Call ESSOut + +; DMA mode + + Mov AL, 0B9h + Call ESSOut + Mov AL, 2 + Call ESSOut + +; Mixspeed + + Mov AL, 0A1h + Call ESSOut + Mov AL, ESSMixConst + Call ESSOut + +; Filter clock divider + Mov AL, 0A2h + Call ESSOut + + Mov AL, 0FEh + Call ESSOut + +; DMA counter + Mov CX, DMASize + Neg CX + + Mov AL, 0A4h + Call ESSOut + Mov AL, CL + Call ESSOut + Mov AL, 0A5h + Call ESSOut + Mov AL, CH + Call ESSOut + +; Initialise DAC + Mov AL, 0B6h + Call ESSOut + Mov AL, 0 + Call ESSOut + +; Configure DACs + + Mov AL, 0B7h + Call ESSOut + Mov AL, 71h + Call ESSOut + + Mov AL, 0B7h + Call ESSOut + + Mov AL, 0BCh + Cmp Stereo, 0 + JNE StartESS2 + + Mov AL, 0F4h + +StartESS2: + Call ESSOut + +; IRQ configuration + Mov AL, 0B1h + Call ESSOut + Mov AL, 50h + Call ESSOut + +; DMA configuration + Mov AL, 0B2h + Call ESSOut + Mov AL, 50h + Call ESSOut + +; Enable voice + Mov AL, 0D1h + Call ESSOut + +; Start transfer + Mov AH, 0B8h + Call ESSReadRegister + Mov AH, AL + Mov AL, 0B8h + Call ESSOut + Mov AL, AH + Or AL, 1 + Call ESSOut + +; Init UART + Mov DX, MIDIPort + Inc DX + Mov AL, 3Fh ; Intelligent mode. + Out DX, AL + +; Enable MIDI IRQ + Mov DX, BasePort + Add DL, 4 + Mov AX, 4064h + Out DX, AX + + Pop DS + Pop ES + PopA + + Ret + +EndP StartESS + Assume DS:Nothing + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov SI, Offset RelocationTable + +RelocationFix: + LodsW + Test AX, AX + JZ RelocationEnd + Mov BX, AX + Mov [BX], DS + Jmp RelocationFix + + +RelocationEnd: + Call GetEMSPageFrame + Mov EMSPageFrame, AX + + In AL, 0A1h + Mov AH, AL + In AL, 21h + Mov IMR, AX + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + Mov DX, BasePort + Add DL, 4 + Mov AL, 22h + Out DX, AL + Inc DX + In AL, DX + Mov AH, AL + And AX, 0FF0h + ShR AH, 1 + ShR AL, 5 + Mov Word Ptr [VolumeTable], AX + + Call GetESSMixConst + + Mov AX, 2643 + Mul MixSpeed + Add AX, 0FFFFh + AdC DX, 2080 + + Mov BX, (DMABUFFERLENGTH*2)/16 + Add BX, DX + + ; Allocate MixSegment first + Mov AH, 48h + + Int 21h + JNC InitSound1 + +InitSoundNoMemory: + Mov SI, Offset ESSNoMemoryMsg + Ret + +InitSound1: + Mov MixSegment, AX + Add AX, DX + Mov DMASegment, AX + + Call SetIRQ + Call GetTempo + Call SetTempo + + Mov SI, Offset ESSMsg + + Mov AX, BasePort + Mov BX, IRQ + Mov CX, DMA + + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Call ResetIRQ + Call SetIRQ + + Mov SI, Offset ReInitMsg + Mov BX, 40 + Call SetInfoLine + + Mov AL, Stereo + Call SetStereo + + Pop ES + Pop DS + PopA + + Ret + +EndP ReInitSound + Assume DS:Nothing + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, IMR + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Mov AX, MixSegment + Test AX, AX + JZ UnInitSound1 + + Mov ES, AX + Mov AH, 49h ; Release MixSegment + Int 21h + + Call ResetDSP + Call ResetIRQ + +UnInitSound1: + Ret + +EndP UnInitSound + Assume DS:Nothing + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + Push CS + Pop DS + Assume DS:Driver + +Poll1: + Call [UARTBufferEmpty] + JNC PollEnd + + Xor BX, BX + + ClI + + Mov BL, MIDIBufferHead + Cmp BL, MIDIBufferTail + JZ PollEnd ; Nothing in queue + + Inc BL + Mov AL, [MIDIBuffer+BX] + Mov MIDIBufferHead, BL + + Call [UARTSend] + Jmp Poll1 + +PollEnd: + StI + + Ret + +EndP Poll + Assume DS:Nothing + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Push AX + Push BX + Push DX + + Push BX + + Mov AX, MixSpeed + Mov BX, AX + Xor DX, DX + + ShL AX, 1 + RCL DX, 1 ; DX:AX = Mixspeed*2 + + ShR BX, 1 ; BX = Mixspeed/2 + + Add AX, BX + AdC DX, 0 ; DX:AX = Mixspeed*2.5 + + Pop BX ; BX = tempo + Div BX + + Mov BytesToMix, AX + + Pop DX + Pop BX + Pop AX + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + PushA + Push DS + + Mov BX, AX ; BX = MixVolume + Mov CS:MixVolume, BX + + Mov AX, CS:MixSegment + Test AX, AX + JZ SetMixVolume2 + + Mov DS, AX + + Mov CX, MIXTABLESIZE/2 + Mov SI, MIXTABLESIZE-2; Starting point - working backwards + +SetMixVolume1: + Mov AX, CX + + Dec AX ; AH = volume, AL = wave value. + Xor DX, DX + XChg AH, DL ; DL = Volume, AX = wave value + CBW + + IMul DX ; DX:AX = Volume * Wave Value + ; Ranges -8192->8128 + + IMul BX ; DX:AX = Volume * Wave Value * Mixing Volume + ; Ranges -1048576->1040384 + + Add AX, 64 + AdC DX, 0 + + ShRD AX, DX, 7 + Mov [SI], AX + Sub SI, 2 + + Loop SetMixVolume1 + +SetMixVolume2: + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS:RecalculateAllVolumes + + Pop DS + PopA + + Ret + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Mov CS:Stereo, AL + Cmp CS:MixSegment, 0 + JE SetStereo1 + + Call ResetDSP + Call StartESS + +SetStereo1: + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include loadsam.inc + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset ESSScreenList + + ClC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far + + Xor AH, AH + Mov AL, [CS:VolumeTable+DI] + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far + + Push DS + Push DX + + Push CS + Pop DS + Assume DS:Driver + + Mov [VolumeTable+DI], AL + + Mov DX, BasePort + Add DL, 4 + Mov AL, 22h + Out DX, AL + Mov AH, [VolumeTable] + ShL AH, 4 + Or AH, [VolumeTable+1] + ShL AH, 1 + Out DX, AX + + Pop DX + Pop DS + Ret + +EndP SetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. + +StopAfterPlay DW 0 +DefaultChannels DW 64 + DW 5 Dup (0) + + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/ES1868MX.ASM b/SoundDrivers/ES1868MX.ASM new file mode 100755 index 0000000..36f4721 --- /dev/null +++ b/SoundDrivers/ES1868MX.ASM @@ -0,0 +1,1734 @@ +; +; ESS Technology's ES1868 AudioDrive chip. +; + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc +include mmx.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;********************************** + +PNPSERIALID EQU 0FFFFFFFFh +PNPVENDORID EQU 68187316h + +STEREOENABLED EQU 1 +DMABUFFERLENGTH EQU 8192 +MIXRESOLUTION EQU 32 ; 32 bit mixing for +OUTPUTFILTERENABLED EQU 0 + +FPSave DB 128 Dup (0) + +ESSMsg DB "ESS ES1868 AudioDrive MMX", 13 + DB "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, DMA ", 0FDh, "D", 0 + +ESSNoMemoryMsg DB "ESS ES1868 AudioDrive MMX", 13 + DB "Error: Insufficient memory", 0 + +ReinitMsg DB "ESS ES1868 AudioDrive reinitialised", 0 + +ConfigErrorMsg DB "Error saving configuration to ITES1868.MMX", 0 +ConfigOKMsg DB "Configuration saved to ITES1868.MMX", 0 + +DriverName DB "ITES1868.MMX", 0 + +ALIGN 4 +ESSMixConst DB 0, 0 + +DMASize DW 2048 ; Smaller gives better MIDI timing +ConfigPort DW 0 + +Forced DB 0 +Stereo DB 0 +MixVolume DW 0 + +BytesToMix DW 1000 + +MixSegment DW 0 + +MixTransferOffset DW 0 +MixTransferRemaining DW 0 + +CONFIGURATIONOFFSET EQU $+128 +CONFIGSIZE EQU 4 +MixMode DW 0 +MixModeOffset DW 0 + +IMR DW 0 +OldESSIRQHandler DD 0 + +IRQData Label Word + DW 20h, 1111111111111110b ; IRQ 0 + DW 24h, 1111111111111101b ; IRQ 1 + DW 28h, 1111110111111011b ; IRQ 2 + DW 2Ch, 1111111111110111b ; IRQ 3 + DW 30h, 1111111111101111b ; IRQ 4 + DW 34h, 1111111111011111b ; IRQ 5 + DW 38h, 1111111110111111b ; IRQ 6 + DW 3Ch, 1111111101111111b ; IRQ 7 + DW 1C0h, 1111111011111011b ; IRQ 8 + DW 1C4h, 1111110111111011b ; IRQ 9 + DW 1C8h, 1111101111111011b ; IRQ 10 + DW 1CCh, 1111011111111011b ; IRQ 11 + DW 1D0h, 1110111111111011b ; IRQ 12 + DW 1D4h, 1101111111111011b ; IRQ 13 + DW 1D8h, 1011111111111011b ; IRQ 14 + DW 1DCh, 0111111111111011b ; IRQ 15 + +ESSScreenList Label + DW 6 + DW Near Ptr IdleFunctionList + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr ESSHeaderLine + + DW Near Ptr DriverText + + DW Near Ptr MixModeText + DW Near Ptr MixModeButton1 ; 6 + DW Near Ptr MixModeButton2 ; + DW Near Ptr MixModeButton3 ; 8 + DW Near Ptr MixModeButton4 ; 9 + + DW 0 + +ESSHeaderLine DW 10 + DB "ESS ES1868 AudioDrive MMX Driver", 0 + +EmptyObject DW 1 + DB 0, 0 + DB 0 + DB 0 + +DriverText DW 1 + DB 22, 48 + DB 21h + DB "ESS ES1868 AudioDrive MMX Driver 1.0 for Impulse Tracker", 0 + +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +IdleFunctionList DD 0 + DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +MixModeText DW 1 + DB 2, 14 + DB 20h + DB "Mixing Mode, Playback Frequency: ", 0FDh, "DHz", 0 +MixSpeed DW 44100 + DW 0 + +MixModeButton1 DW 2 + DW 0FFFFh, 7, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment1 DW 0 + DW 0 + DW Offset SetMixMode +DriverSegment2 DW 0 + DB 3, 16, 32, 18, 8 + DB 0 + DB " MMX, Non-Interpolated", 0 + +MixModeButton2 DW 2 + DW 6, 8, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment3 DW 0 + DW 1 + DW Offset SetMixMode +DriverSegment4 DW 0 + DB 3, 19, 32, 21, 8 + DB 0 + DB " MMX, Interpolated", 0 + +MixModeButton3 DW 2 + DW 7, 9, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment5 DW 0 + DW 2 + DW Offset SetMixMode +DriverSegment6 DW 0 + DB 3, 22, 32, 24, 8 + DB 0 + DB " MMX, Volume Ramped", 0 + +MixModeButton4 DW 2 + DW 8, 0FFFFh, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment7 DW 0 + DW 3 + DW Offset SetMixMode +DriverSegment8 DW 0 + DB 3, 25, 32, 27, 8 + DB 0 + DB " MMX, Filtered", 0 + +ALIGN 4 + +VolumeTable DB 2 Dup (0) +MIDIPort DW 0 + +MIDIBuffer DB 256 Dup (0) +MIDIBufferHead DB 0 +MIDIBufferTail DB 0 + +; ÄÄ MixingRoutines ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixBufferPos DW 0 + +include dma.inc +include mix.inc + +include m32bitm.mix +include m32bitmi.mix +include m32bitmv.mix +include m32bitmf.mix + +ALIGN 2 + +MixFunctionTables Label + +include m32bitm.inc +include m32bitmi.inc +include m32bitmv.inc +include m32bitmf.inc +include mnomix.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +RelocationTable Label Word + DW Offset DriverSegment1, Offset DriverSegment2 + DW Offset DriverSegment3, Offset DriverSegment4 + DW Offset DriverSegment5, Offset DriverSegment6 + DW Offset DriverSegment7, Offset DriverSegment8 + DW 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ESSOut ; AL = data + ; DX = 2xCh + + Push AX + +ESSOut1: + In AL, DX + Test AL, AL + JS ESSOut1 + + Pop AX + Out DX, AL + + Ret + +EndP ESSOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ESSIn ; DX = 2xCh, returns AL + +ESSIn1: + In AL, DX + Test AL, 40h + JZ ESSIn1 + + Add DL, 0Ah-0Ch ; DX = 2xAh -> Data read port + In AL, DX + Add DL, 0Ch-0Ah + + Ret + +EndP ESSIn + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UARTOut ; AL = out + + Push DX + Push AX + + Mov DX, CS:MIDIPort + Inc DX + +UARTOut1: + In AL, DX + Test AL, 40h + JNZ UARTOut1 + + Pop AX + Dec DX + Out DX, AL + + Pop DX + Ret + +EndP UARTOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UARTIn ; returns AL + + Push DX + + Mov DX, CS:MIDIPort + Inc DX + +UARTIn1: + In AL, DX + Test AL, 80h + JNZ UARTIn1 + + Dec DX + In AL, DX + + Pop DX + Ret + +EndP UARTIn + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ESSReadRegister ; AH = register to read. + ; DX = 2xCh + ; returns AL + + Mov AL, 0C0h + Call ESSOut + Mov AL, AH + Call ESSOut + Call ESSIn + + Ret + +EndP ESSReadRegister + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixMode Far + + Push CS + Pop ES + Mov DI, Offset MixMode + + Ret + +EndP GetMixMode + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixMode Far + + Mov AX, [SI+22] + + ClI + + Mov CS:MixMode, AX + + Mov BX, 60 + Mul BX + Mov CS:MixModeOffset, AX + + StI + + Mov AX, 1 + Ret + +EndP SetMixMode + Assume DS:Nothing + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +PnP_SerialID DD 0 +PnP_VendorID DD 0 +PnP_ReadPort DW 0 +PnP_CSN DB 0 +PnP_CardFound DB 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_Delay + Assume DS:Driver + + Push AX CX + + Mov CX, 180h +PnP_Delay1: + In AL, 21h + Loop PnP_Delay1 + + Pop CX AX + Ret + +EndP PnP_Delay + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_WriteData + + Mov DX, 279h + Out DX, AL + + Mov AL, AH + Mov DH, 0Ah + Out DX, AL + Ret + +EndP PnP_WriteData + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_ReadData + + Mov DX, 279h + Out DX, AL + + Mov DX, PnP_ReadPort + In AL, DX + + Ret + +EndP PnP_ReadData + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_Isolate + + Mov AX, 402h + Call Pnp_WriteData ; Reset CSNs + +PnP_IsolateNextCard: + Mov AX, 0003h + Call PnP_WriteData ; Wake[0] + + Mov AX, PnP_ReadPort + ShL AX, 6 + Xor AL, AL + Call PnP_WriteData ; Set Read Data port. + + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + + Mov AL, 1 ; Serial Isolation + Mov DX, 279h + Out DX, AL + + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + + Mov BL, 6Ah + Mov CX, 64 + Mov DX, PnP_ReadPort + + ClI + +PnP_Isolate1: + ShR PnP_SerialID, 1 + RCR PnP_VendorID, 1 + + Mov BH, BL + ShR BH, 1 + Xor BH, BL + ShR BX, 1 + + In AL, DX + Mov AH, AL + Call PnP_Delay + In AL, DX + Call PnP_Delay + + Cmp AX, 55AAh + JNE PnP_Isolate2 + + Xor BL, 80h + Or PnP_SerialID, 80000000h + +PnP_Isolate2: + Dec CX + JNZ PnP_Isolate1 + + Mov CX, 8 + Xor BH, BH + +PnP_Isolate3: + ShR BH, 1 + + In AL, DX + Mov AH, AL + Call PnP_Delay + In AL, DX + Call PnP_Delay + Cmp AX, 55AAh + JNE PnP_Isolate4 + + Or BH, 80h + +PnP_Isolate4: + Dec CX + JNZ PnP_Isolate3 + + StI + + Cmp BL, BH ; Matching Checksum? + JNE PnP_IsolateFinished + + ; assign CSN + Inc PnP_CSN + + Mov AL, 6 + MOv AH, PnP_CSN + Call PnP_WriteData + +; Cmp PnP_VendorID, PNPVENDORID +; JNE PnP_IsolateNextCard + Cmp PnP_SerialID, PNPSERIALID + JNE PnP_IsolateNextCard + + Mov AL, 3 + Call PnP_WriteData + + Mov AX, 07h ; Configuration device + Call PnP_WriteData + + Mov AL, 60h + Call PnP_ReadData + Mov AH, AL + Mov AL, 61h + Call PnP_ReadData ; AX = address. + Mov ConfigPort, AX + + Mov AX, 107h ; Audio device + Call PnP_WriteData + + Mov AL, 64h + Call PnP_ReadData + Mov AH, AL + Mov AL, 65h + Call PnP_ReadData ; AX = address. + Mov MIDIPort, AX + + Mov AL, 60h + Call PnP_ReadData + Mov AH, AL + Mov AL, 61h + Call PnP_ReadData ; AX = address. + Cmp BasePort, 0FFFFh + JE PnPBasePortOK + + Cmp BasePort, AX + JNE PnP_IsolateNextCard + +PnPBasePortOK: + Mov BasePort, AX + + Mov AL, 70h + Call PnP_ReadData ; AL[3:0] = IRQ + And AX, 15 + JZ PnP_IsolateNextCard + Mov IRQ, AX + + Mov AL, 74h + Call PnP_ReadData ; AL[2:0] = DMA + And AX, 7 + Cmp AL, 4 + JE PnP_IsolateNextCard + Mov DMA, AX + + Mov Pnp_CardFound, 1 + Jmp PnP_IsolateNextCard + +PnP_IsolateFinished: + Mov AL, PnP_CSN + ShL AL, 1 + Or AL, PnP_CardFound + + Ret + +EndP PnP_Isolate + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far ; returns carry clear if succesful + + Push CS + Pop DS + + Xor AL, AL + Mov DX, 279h + Out DX, AL + Out DX, AL + + Mov AL, 6Ah ; Starting value + Mov CX, 32 + +PnP_InitiationKeyLoop: + Out DX, AL + + Mov AH, AL + ShR AH, 1 + Xor AH, AL + ShR AX, 1 + + Dec CX + JNZ PnP_InitiationKeyLoop + +; Try three ports before concluding no PnP cards: 20Fh, 27Bh, 213h + +PnP_DetectCardPort1: + Mov PnP_ReadPort, 20Fh + Call PnP_Isolate + JZ PnP_DetectCardPort2 + Test AL, 1 + JZ PnP_DetectCardNotFound + Jmp PnP_DetectCardFound + +PnP_DetectCardPort2: + Mov PnP_ReadPort, 27Bh + Call PnP_Isolate + JZ PnP_DetectCardPort3 + Test AL, 1 + JZ PnP_DetectCardNotFound + Jmp PnP_DetectCardFound + +PnP_DetectCardPort3: + Mov PnP_ReadPort, 213h + Call PnP_Isolate + Test AL, 1 + JNZ PnP_DetectCardFound + +PnP_DetectCardNotFound: + StC + Jmp PnP_DetectEnd + +PnP_DetectCardFound: + ClC + +PnP_DetectEnd: ; Return PnP to wait for key state + Mov AX, 202h + Call PnP_WriteData + Mov EAX, 'Jeff' + + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetDSP Far ; AX = Port + + Push AX + Push CX + Push DX + + Mov DX, CS:MIDIPort + Inc DX + Mov AL, 0FFh + Out DX, AL + + Mov DX, CS:BasePort + Add DL, 6 + Mov AL, 3 + Out DX, AL + + In AL, DX + In AL, DX + In AL, DX + In AL, DX + + Xor AL, AL + Out DX, AL + + Add DL, 8 + Mov CX, 200 + +ResetDSP1: + In AL, DX + Test AL, AL + JS ResetDSP2 + Loop ResetDSP1 + Jmp ResetDSP3 + +ResetDSP2: + Sub DL, 4 + In AL, DX + Cmp AL, 0AAh + JE ResetDSP4 + Add DL, 4 + Loop ResetDSP1 + +ResetDSP3: + StC + +ResetDSP4: + Pop DX + Pop CX + Pop AX + Ret + +EndP ResetDSP + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include mmxmsam.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc CheckMIDI + + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Xor BX, BX + Call UARTIn + Mov BL, [MIDIBufferTail] + + Cmp AL, 0F0h + JAE CheckMIDIEnd + + Inc BL + Cmp BL, MIDIBufferHead + JE CheckMIDIEnd + + Mov [MIDIBuffer+BX], AL + Mov [MIDIBufferTail], BL + +CheckMIDIEnd: + Pop DS + Ret + +EndP CheckMIDI + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ESSIRQHandler + + PushAD + Push DS + Push ES + + ClD + + Mov AX, CS + Mov DS, AX + Assume DS:Driver + + Mov DX, [ConfigPort] + Add DL, 6 + In AL, DX + Test AL, 8 + JZ ESSNoMIDI + + Push AX + Call CheckMIDI + Pop AX + +ESSNoMIDI: + Test AL, 1 + JZ ESSIRQEnd + + Mov DX, [BasePort] + Add DL, 0Eh + In AL, DX + + Mov AX, MixBufferPos + Mov BX, AX + Mul DMASize + Cmp AX, DMABUFFERLENGTH + JB ESSIRQHandler2 + + Xor AX, AX + Xor BX, BX + +ESSIRQHandler2: + FNSave [FPSave] + + Inc BX + Mov MixBufferPos, BX + + CLD + + + ; OK... time to get next block + ; Check whether stereo thing is on.. + ; + LES DI, [ActualDMAPtr] + Add DI, AX + + Mov BX, DMASize ; BX = bytes required + ShR BX, 1 + ; BX = samples required + Mov BP, 8 ; Skip for mono + Mov CL, 14 ; Shift for mono + + Cmp Stereo, 0 + JE ESSIRQHandlerMono + + Mov BP, 4 ; Stereo skip value. + Dec CL + +ESSIRQHandlerMono: + Call SaveEMSPageFrame + + Cmp MixTransferRemaining, 0 + JNE ESSIRQHandler4 + Assume DS:Nothing + +ESSIRQHandler3: + Push BX + Push CX + Push BP + Push ES + Push DI + + Call Update + Call MixSamples + + Pop DI + Pop ES + Pop BP + Pop CX + Pop BX + +ESSIRQHandler4: + Mov DS, MixSegment + Mov SI, MixTransferOffset + Mov DX, BX ; DX = samples to transfer + Cmp DX, MixTransferRemaining + JBE ESSIRQHandler5 + + Mov DX, MixTransferRemaining + +ESSIRQHandler5: + +include mmxtrans.inc + + Sub MixTransferRemaining, DX ; } Memory write + Sub BX, DX + JNZ ESSIRQHandler3 + + Mov MixTransferOffset, SI ; } Memory write + + Call RestoreEMSPageFrame + + FNRStor [CS:FPSave] + +ESSIRQEnd: + Mov AL, 20h + Cmp IRQ, 8 + JB WSSAckIRQ1 + + Out 0A0h, AL + +WSSAckIRQ1: + Out 20h, AL + + Pop ES + Pop DS + PopAD + IRet + +EndP ESSIRQHandler + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Add DI, Offset IRQData + Mov BX, [CS:DI] + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset ESSIRQHandler + + XChg [ES:BX], EAX + Mov OldESSIRQHandler, EAX + + Mov AX, IMR + And AX, [DI+2] + + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Pop ES + PopAD + + Ret + +EndP SetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Mov BX, [IRQData+DI] + + Mov EAX, OldESSIRQHandler + Mov [ES:BX], EAX + + Pop ES + PopAD + + Ret + +EndP ResetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetESSMixConst + + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, CmdLineMixSpeed + Mov CX, MixSpeed + Test AX, AX + JZ GetESSMixConst1 + + Mov CX, 22050 + Cmp AX, CX + JB GetESSMixConst1 + + Mov CX, 56821 + Cmp AX, CX + JA GetESSMixConst1 + + Mov CX, AX + +GetESSMixConst1: ; CX = mixspeed. + Mov DX, 0Ch + Mov AX, 236Ch ; DX:AX = 795.5kHz + Div CX + + Mov BX, AX + Neg AL + Mov ESSMixConst, AL + + Mov DX, 0Ch + Mov AX, 236Ch + Div BX + Mov MixSpeed, AX + + FNInit + FILd DWord Ptr [MixSpeed] + FMul FreqMultiplier + FStP FreqMultiplier + + Pop DS + PopA + Ret + +EndP GetESSMixConst + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StartESS + + PushA + Push ES + Push DS + + Push CS + Pop DS + Assume DS:Driver + + ; Setup DMA + Mov BX, MixSegment + Mov AX, 80 + Mov DX, DMA + Mov DI, DMABUFFERLENGTH + Call SetDMA + + LES DI, ActualDMAPtr + Xor AX, AX + Mov CX, DMABUFFERLENGTH/2 + Rep StosW + + Mov MixBufferPos, 0 + Mov MixTransferRemaining, 0 + + Call ResetDSP + Mov DX, BasePort + Add DL, 0Ch + +; Extended Functions + + Mov AL, 0C6h + Call ESSOut + +; Autoinit DMA + + Mov AL, 0B8h + Call ESSOut + Mov AL, 4 + Call ESSOut + +; Stereo/Mono select + + Mov AH, 0A8h + Call ESSReadRegister + Mov AH, AL + Mov AL, 0A8h + Call ESSOut + Mov AL, AH + And AL, Not 3 + Or AL, 2 + Cmp Stereo, 0 + JE StartESS1 + + Xor AL, 3 + +StartESS1: + Call ESSOut + +; DMA mode + + Mov AL, 0B9h + Call ESSOut + Mov AL, 2 + Call ESSOut + +; Mixspeed + + Mov AL, 0A1h + Call ESSOut + Mov AL, ESSMixConst + Call ESSOut + +; Filter clock divider + Mov AL, 0A2h + Call ESSOut + + Mov AL, 0FEh + Call ESSOut + +; DMA counter + Mov CX, DMASize + Neg CX + + Mov AL, 0A4h + Call ESSOut + Mov AL, CL + Call ESSOut + Mov AL, 0A5h + Call ESSOut + Mov AL, CH + Call ESSOut + +; Initialise DAC + Mov AL, 0B6h + Call ESSOut + Mov AL, 0 + Call ESSOut + +; Configure DACs + + Mov AL, 0B7h + Call ESSOut + Mov AL, 71h + Call ESSOut + + Mov AL, 0B7h + Call ESSOut + + Mov AL, 0BCh + Cmp Stereo, 0 + JNE StartESS2 + + Mov AL, 0F4h + +StartESS2: + Call ESSOut + +; IRQ configuration + Mov AL, 0B1h + Call ESSOut + Mov AL, 50h + Call ESSOut + +; DMA configuration + Mov AL, 0B2h + Call ESSOut + Mov AL, 50h + Call ESSOut + +; Enable voice + Mov AL, 0D1h + Call ESSOut + +; Start transfer + Mov AH, 0B8h + Call ESSReadRegister + Mov AH, AL + Mov AL, 0B8h + Call ESSOut + Mov AL, AH + Or AL, 1 + Call ESSOut + +; Init UART + Mov DX, MIDIPort + Inc DX + Mov AL, 3Fh ; Intelligent mode. + Out DX, AL + +; Enable MIDI IRQ + Mov DX, BasePort + Add DL, 4 + Mov AX, 4064h + Out DX, AX + + Pop DS + Pop ES + PopA + + Ret + +EndP StartESS + Assume DS:Nothing + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov SI, Offset RelocationTable + +RelocationFix: + LodsW + Test AX, AX + JZ RelocationEnd + Mov BX, AX + Mov [BX], DS + Jmp RelocationFix + + +RelocationEnd: + Call GetEMSPageFrame + Mov EMSPageFrame, AX + + In AL, 0A1h + Mov AH, AL + In AL, 21h + Mov IMR, AX + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + Mov DX, BasePort + Add DL, 4 + Mov AL, 22h + Out DX, AL + Inc DX + In AL, DX + Mov AH, AL + And AX, 0FF0h + ShR AH, 1 + ShR AL, 5 + Mov Word Ptr [VolumeTable], AX + + Call GetESSMixConst + + Mov AX, 2643 + Mul MixSpeed + Add AX, 0FFFFh + AdC DX, (DMABUFFERLENGTH*2)/16+5 + Mov BX, DX + Mov AH, 48h + + Int 21h + JNC InitSound1 + +InitSoundNoMemory: + Mov SI, Offset ESSNoMemoryMsg + Ret + +InitSound1: + Mov MixSegment, AX + + Call SetIRQ + Call GetTempo + Call SetTempo + + Mov SI, Offset ESSMsg + + Mov AX, BasePort + Mov BX, IRQ + Mov CX, DMA + + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Call ResetIRQ + Call SetIRQ + + Mov SI, Offset ReInitMsg + Mov BX, 40 + Call SetInfoLine + + Mov AL, Stereo + Call SetStereo + + Pop ES + Pop DS + PopA + + Ret + +EndP ReInitSound + Assume DS:Nothing + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Call GotoHomeDirectory + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, 3D02h ; Read write access + Mov DX, Offset DriverName + Int 21h + JC SaveConfig2 + + Mov BX, AX + + Mov AX, 4200h + Xor CX, CX + Mov DX, Offset CONFIGURATIONOFFSET + Int 21h + JC SaveConfig1 + + Mov AH, 40h + Mov CX, CONFIGSIZE + Mov DX, Offset MixMode + Int 21h + +SaveConfig1: + Mov AH, 3Eh + Int 21h + +SaveConfig2: + Mov AX, IMR + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Mov AX, MixSegment + Test AX, AX + JZ UnInitSound1 + + Mov ES, AX + Mov AH, 49h ; Release MixSegment + Int 21h + + Call ResetDSP + Call ResetIRQ + +UnInitSound1: + Ret + +EndP UnInitSound + Assume DS:Nothing + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + Push CS + Pop DS + Assume DS:Driver + +Poll1: + Call [UARTBufferEmpty] + JNC PollEnd + + Xor BX, BX + + ClI + + Mov BL, MIDIBufferHead + Cmp BL, MIDIBufferTail + JZ PollEnd ; Nothing in queue + + Inc BL + Mov AL, [MIDIBuffer+BX] + Mov MIDIBufferHead, BL + + Call [UARTSend] + Jmp Poll1 + +PollEnd: + StI + + Ret + +EndP Poll + Assume DS:Nothing + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Push AX + Push BX + Push DX + + Push BX + + Mov AX, MixSpeed + Mov BX, AX + Xor DX, DX + + ShL AX, 1 + RCL DX, 1 ; DX:AX = Mixspeed*2 + + ShR BX, 1 ; BX = Mixspeed/2 + + Add AX, BX + AdC DX, 0 ; DX:AX = Mixspeed*2.5 + + Pop BX ; BX = tempo + Div BX + + Mov BytesToMix, AX + + Pop DX + Pop BX + Pop AX + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + Mov CS:MixVolume, AX + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Jmp CS:RecalculateAllVolumes + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Mov CS:Stereo, AL + Cmp CS:MixSegment, 0 + JE SetStereo1 + + Call ResetDSP + Call StartESS + +SetStereo1: + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include loadsam.inc + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset ESSScreenList + + ClC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far + + Xor AH, AH + Mov AL, [CS:VolumeTable+DI] + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far + + Push DS + Push DX + + Push CS + Pop DS + Assume DS:Driver + + Mov [VolumeTable+DI], AL + + Mov DX, BasePort + Add DL, 4 + Mov AL, 22h + Out DX, AL + Mov AH, [VolumeTable] + ShL AH, 4 + Or AH, [VolumeTable+1] + ShL AH, 1 + Out DX, AX + + Pop DX + Pop DS + Ret + +EndP SetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +InterpretState DB 0 +InterpretType DB 0 + +Proc SendUARTOut Far ; Local interpreter activated with 0F0h 0F0h. + + Mov AH, CS:InterpretState + Cmp AH, 2 + JB SendUARTOut1 + +; In interpreter. + JE SendUARTOut3 + +; Have InterpretType, now get parameter, then return to normal. + + Cmp AL, 7Fh + JA SendUARTOut4 + + Push BX + + Mov BL, CS:InterpretType ; Want BX = InterpretType*64+Channel + ; + ShL BX, 6 + Add BL, [DI+20h] + And BX, 127 + Mov [CS:FilterParameters+BX], AL + + Pop BX + + Test SI, SI + JZ SendUARTOut4 + + Or Byte Ptr [SI], 64 + +SendUARTOut4: + Mov CS:InterpretState, 0 + Ret + +SendUARTOut3: + Cmp AL, 2 + JAE SendUARTOut4 + + Mov CS:InterpretType, AL + Jmp SendUARTOutStateInc + +SendUARTOut1: + Cmp AL, 0F0h + JNE SendUARTOut2 + +SendUARTOutStateInc: + Inc CS:InterpretState + Ret + +SendUARTOut2: + Test AH, AH + JZ SendUARTOutEnd + + Push AX + Mov AL, 0F0h + Call UARTOut + Pop AX + Mov CS:InterpretState, 0 + +SendUARTOutEnd: + Cmp AL, 0FCh + JE ResetFilters + Cmp AL, 0FAh + JE ResetFilters + + Cmp AL, 0FFh + JNE SendUARTOutNoClear + +ResetFilters: + PushA + Push ES + + Push CS + Pop ES + + Mov DI, Offset FilterParameters + Mov CX, 64 + Mov AL, 7Fh + Rep StosB + Mov CX, 64 + Xor AX, AX + Rep StosB + + Pop ES + PopA + +SendUARTOutNoClear: + Call UARTOut + Ret + +EndP SendUARTOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. + +StopAfterPlay DW 0 +DefaultChannels DW 128 + DW 3 ; MIDI, hiqual + DW 4 Dup (0) + + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + DW Offset SendUARTOut + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/ES1869.ASM b/SoundDrivers/ES1869.ASM new file mode 100755 index 0000000..d85d4f5 --- /dev/null +++ b/SoundDrivers/ES1869.ASM @@ -0,0 +1,2328 @@ +; +; ESS Technology's ES1869 AudioDrive chip. +; + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;********************************** + +PNPSERIALID EQU 0FFFFFFFFh +PNPVENDORID EQU 03007316h + +STEREOENABLED EQU 1 +DMABUFFERLENGTH EQU 8192 +MIXRESOLUTION EQU 32 ; 32 bit mixing for +MIXTABLESIZE EQU 2*256*65 + +ESSMsg DB "ESS ES1869 AudioDrive found", 13 + DB "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, DMA ", 0FDh, "D", 0 + +ESSNoMemoryMsg DB "ESS ES1869 AudioDrive found", 13 + DB "Error: Insufficient memory", 0 + +ReinitMsg DB "ESS ES1869 AudioDrive reinitialised", 0 + +ConfigErrorMsg DB "Error saving configuration to ITES1869.DRV", 0 +ConfigOKMsg DB "Configuration saved to ITES1869.DRV", 0 + +DriverName DB "ITES1869.DRV", 0 + +ALIGN 4 +FilterValue DD 0 +FilterValue2 DD 0 +ESSMixConst DB 0, 0 + +DMASize DW 2048 ; Smaller gives better MIDI timing +ConfigPort DW 0 + +Forced DB 0 +Stereo DB 0 +MixVolume DW 0 + +BytesToMix DW 1000 + +MixSegment DW 0 +DMASegment DW 0 + +MixTransferOffset DW 0 +MixTransferRemaining DW 0 + +CONFIGURATIONOFFSET EQU $+128 +CONFIGSIZE EQU 6 +MixMode DW 0 +MixModeOffset DW 0 +Filter DW 0 + +IMR DW 0 +OldESSIRQHandler DD 0 + +IRQData Label Word + DW 20h, 1111111111111110b ; IRQ 0 + DW 24h, 1111111111111101b ; IRQ 1 + DW 28h, 1111110111111011b ; IRQ 2 + DW 2Ch, 1111111111110111b ; IRQ 3 + DW 30h, 1111111111101111b ; IRQ 4 + DW 34h, 1111111111011111b ; IRQ 5 + DW 38h, 1111111110111111b ; IRQ 6 + DW 3Ch, 1111111101111111b ; IRQ 7 + DW 1C0h, 1111111011111011b ; IRQ 8 + DW 1C4h, 1111110111111011b ; IRQ 9 + DW 1C8h, 1111101111111011b ; IRQ 10 + DW 1CCh, 1111011111111011b ; IRQ 11 + DW 1D0h, 1110111111111011b ; IRQ 12 + DW 1D4h, 1101111111111011b ; IRQ 13 + DW 1D8h, 1011111111111011b ; IRQ 14 + DW 1DCh, 0111111111111011b ; IRQ 15 + +ESSScreenList Label + DW 6 + DW Near Ptr IdleFunctionList + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr ESSHeaderLine + + DW Near Ptr DriverText + + DW Near Ptr MixModeText + DW Near Ptr MixModeButton1 ; 6 + DW Near Ptr MixModeButton2 ; + DW Near Ptr MixModeButton3 ; 8 + DW Near Ptr MixModeButton4 ; 9 + + DW Near Ptr FilterText + DW Near Ptr FilterButton1 ; 11 + DW Near Ptr FilterButton2 + DW Near Ptr FilterButton3 + +Comment ~ + + DW Near Ptr VolumeText + DW Near Ptr VolumeBox1 + + DW Near Ptr MasterVolumeLeft ; 16 + DW Near Ptr MasterVolumeRight ; 17 + +~ + + DW 0 + +ESSHeaderLine DW 10 + DB "ESS ES1869 AudioDrive Driver", 0 + +EmptyObject DW 1 + DB 0, 0 + DB 0 + DB 0 + +DriverText DW 1 + DB 26, 48 + DB 21h + DB "ESS ES1869 AudioDrive Driver 1.0 for Impulse Tracker", 0 + +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +IdleFunctionList DD 0 + DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +Comment ~ + +VolumeText DW 1 + DB 2, 14 + DB 20h + DB "Master Volume Left", 13 + DB "Master Volume Right" + DB 0 + +VolumeBox1 DW 0 + DB 21, 13, 31, 16 + DB 25 + +MasterVolumeLeft DW 14 + DB 22, 14 + DW 0, 15 + DW 9, 0 + DW 0FFFFh, 17, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 8 + +MasterVolumeRight DW 14 + DB 22, 15 + DW 0, 15 + DW 9, 1 + DW 16, 6, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 8 + +~ + +MixModeText DW 1 + DB 2, 14 + DB 20h + DB "Mixing Mode, Playback Frequency: ", 0FDh, "DHz", 0 +MixSpeed DW 44100 + +MixModeButton1 DW 2 + DW 0FFFFh, 7, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment1 DW 0 + DW 0 + DW Offset SetMixMode +DriverSegment2 DW 0 + DB 3, 16, 32, 18, 8 + DB 0 + DB " 16 Bit, Non-Interpolated", 0 + +MixModeButton2 DW 2 + DW 6, 8, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment3 DW 0 + DW 2 + DW Offset SetMixMode +DriverSegment4 DW 0 + DB 3, 19, 32, 21, 8 + DB 0 + DB " 16 Bit, Interpolated", 0 + +MixModeButton3 DW 2 + DW 7, 9, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment5 DW 0 + DW 4 + DW Offset SetMixMode +DriverSegment6 DW 0 + DB 3, 22, 32, 24, 8 + DB 0 + DB " 32 Bit, Non-Interpolated", 0 + +MixModeButton4 DW 2 + DW 8, 11, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment7 DW 0 + DW 6 + DW Offset SetMixMode +DriverSegment8 DW 0 + DB 3, 25, 32, 27, 8 + DB 0 + DB " 32 Bit, Interpolated", 0 + +FilterText DW 1 + DB 2, 29 + DB 20h + DB "Filter mode", 0 + +FilterButton1 DW 2 + DW 9, 12, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment9 DW 0 + DW 0 + DW Offset SetFilter +DriverSegment10 DW 0 + DB 3, 31, 29, 33, 8 + DB 0 + DB " No Filter", 0 + +FilterButton2 DW 2 + DW 11, 13, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment11 DW 0 + DW 1 + DW Offset SetFilter +DriverSegment12 DW 0 + DB 3, 34, 29, 36, 8 + DB 0 + DB " 50% Filter", 0 + +FilterButton3 DW 2 + DW 12, 0FFFFh, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment13 DW 0 + DW 2 + DW Offset SetFilter +DriverSegment14 DW 0 + DB 3, 37, 29, 39, 8 + DB 0 + DB " 75% Filter", 0 + +ALIGN 4 + +VolumeTable DB 2 Dup (0) +MIDIPort DW 0 + +MIDIBuffer DB 256 Dup (0) +MIDIBufferHead DB 0 +MIDIBufferTail DB 0 + +; ÄÄ MixingRoutines ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixBufferPos DW 0 + +include dma.inc +include mix.inc +include m12bit.mix +include m12biti.mix +include m32bit.mix +include m32biti.mix + +MixFunctionTables Label + +include m12bit.inc ; contains the tables +include m12biti.inc +include m32bit.inc +include m32biti.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +RelocationTable Label Word + DW Offset DriverSegment1, Offset DriverSegment2 + DW Offset DriverSegment3, Offset DriverSegment4 + DW Offset DriverSegment5, Offset DriverSegment6 + DW Offset DriverSegment7, Offset DriverSegment8 + DW Offset DriverSegment9, Offset DriverSegment10 + DW Offset DriverSegment11, Offset DriverSegment12 + DW Offset DriverSegment13, Offset DriverSegment14 + DW 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ESSOut ; AL = data + ; DX = 2xCh + + Push AX + +ESSOut1: + In AL, DX + Test AL, AL + JS ESSOut1 + + Pop AX + Out DX, AL + + Ret + +EndP ESSOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ESSIn ; DX = 2xCh, returns AL + +ESSIn1: + In AL, DX + Test AL, 40h + JZ ESSIn1 + + Add DL, 0Ah-0Ch ; DX = 2xAh -> Data read port + In AL, DX + Add DL, 0Ch-0Ah + + Ret + +EndP ESSIn + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UARTOut ; AL = out + + Push DX + Push AX + + Mov DX, CS:MIDIPort + Inc DX + +UARTOut1: + In AL, DX + Test AL, 40h + JNZ UARTOut1 + + Pop AX + Dec DX + Out DX, AL + + Pop DX + Ret + +EndP UARTOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UARTIn ; returns AL + + Push DX + + Mov DX, CS:MIDIPort + Inc DX + +UARTIn1: + In AL, DX + Test AL, 80h + JNZ UARTIn1 + + Dec DX + In AL, DX + + Pop DX + Ret + +EndP UARTIn + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ESSReadRegister ; AH = register to read. + ; DX = 2xCh + ; returns AL + + Mov AL, 0C0h + Call ESSOut + Mov AL, AH + Call ESSOut + Call ESSIn + + Ret + +EndP ESSReadRegister + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixMode Far + + Push CS + Pop ES + Mov DI, Offset MixMode + + Ret + +EndP GetMixMode + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetFilter Far + + Push CS + Pop ES + Mov DI, Offset Filter + + Ret + +EndP GetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetFilter Far + + Mov AX, [SI+22] + Mov CS:FilterValue, 0 + Mov CS:Filter, AX + ClI + Jmp SetMixModeChain + +EndP SetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixMode Far + + Mov AX, [SI+22] + + ClI + + Mov CS:MixMode, AX + + Mov BX, 180 + Mul BX + Mov CS:MixModeOffset, AX + + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS:RecalculateAllVolumes + + StI + +SetMixModeChain: + Call GotoHomeDirectory + + ; Now to save config into driver file. + Push CS + Pop DS + Assume DS:Driver + + Mov AX, 3D02h ; Read write access + Mov DX, Offset DriverName + Mov SI, Offset ConfigErrorMsg + Int 21h + JC SetMixMode1 + + Mov BX, AX + + Mov AX, 4200h + Xor CX, CX + Mov DX, Offset CONFIGURATIONOFFSET + Int 21h + JC SetMixMode2 + + Mov AH, 40h + Mov CX, CONFIGSIZE + Mov DX, Offset MixMode + Int 21h + +SetMixMode2: + PushF + Mov AH, 3Eh + Int 21h + PopF + + JC SetMixMode1 + + Mov SI, Offset ConfigOKMsg + +SetMixMode1: + Mov BX, 40 + Call SetInfoLine + + Mov AX, 1 + Ret + +EndP SetMixMode + Assume DS:Nothing + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +PnP_SerialID DD 0 +PnP_VendorID DD 0 +PnP_ReadPort DW 0 +PnP_CSN DB 0 +PnP_CardFound DB 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_Delay + Assume DS:Driver + + Push AX CX + + Mov CX, 180h +PnP_Delay1: + In AL, 21h + Loop PnP_Delay1 + + Pop CX AX + Ret + +EndP PnP_Delay + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_WriteData + + Mov DX, 279h + Out DX, AL + + Mov AL, AH + Mov DH, 0Ah + Out DX, AL + Ret + +EndP PnP_WriteData + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_ReadData + + Mov DX, 279h + Out DX, AL + + Mov DX, PnP_ReadPort + In AL, DX + + Ret + +EndP PnP_ReadData + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_Isolate + + Mov AX, 402h + Call Pnp_WriteData ; Reset CSNs + +PnP_IsolateNextCard: + Mov AX, 0003h + Call PnP_WriteData ; Wake[0] + + Mov AX, PnP_ReadPort + ShL AX, 6 + Xor AL, AL + Call PnP_WriteData ; Set Read Data port. + + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + + Mov AL, 1 ; Serial Isolation + Mov DX, 279h + Out DX, AL + + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + + Mov BL, 6Ah + Mov CX, 64 + Mov DX, PnP_ReadPort + + ClI + +PnP_Isolate1: + ShR PnP_SerialID, 1 + RCR PnP_VendorID, 1 + + Mov BH, BL + ShR BH, 1 + Xor BH, BL + ShR BX, 1 + + In AL, DX + Mov AH, AL + Call PnP_Delay + In AL, DX + Call PnP_Delay + + Cmp AX, 55AAh + JNE PnP_Isolate2 + + Xor BL, 80h + Or PnP_SerialID, 80000000h + +PnP_Isolate2: + Dec CX + JNZ PnP_Isolate1 + + Mov CX, 8 + Xor BH, BH + +PnP_Isolate3: + ShR BH, 1 + + In AL, DX + Mov AH, AL + Call PnP_Delay + In AL, DX + Call PnP_Delay + Cmp AX, 55AAh + JNE PnP_Isolate4 + + Or BH, 80h + +PnP_Isolate4: + Dec CX + JNZ PnP_Isolate3 + + StI + + Cmp BL, BH ; Matching Checksum? + JNE PnP_IsolateFinished + + ; assign CSN + Inc PnP_CSN + + Mov AL, 6 + MOv AH, PnP_CSN + Call PnP_WriteData + +; Cmp PnP_VendorID, PNPVENDORID +; JNE PnP_IsolateNextCard + Cmp PnP_SerialID, PNPSERIALID + JNE PnP_IsolateNextCard + + Mov AL, 3 + Call PnP_WriteData + + Mov AX, 07h ; Configuration device + Call PnP_WriteData + + Mov AL, 60h + Call PnP_ReadData + Mov AH, AL + Mov AL, 61h + Call PnP_ReadData ; AX = address. + Mov ConfigPort, AX + + Mov AX, 107h ; Audio device + Call PnP_WriteData + + Mov AL, 64h + Call PnP_ReadData + Mov AH, AL + Mov AL, 65h + Call PnP_ReadData ; AX = address. + Mov MIDIPort, AX + + Mov AL, 60h + Call PnP_ReadData + Mov AH, AL + Mov AL, 61h + Call PnP_ReadData ; AX = address. + Cmp BasePort, 0FFFFh + JE PnPBasePortOK + + Cmp BasePort, AX + JNE PnP_IsolateNextCard + +PnPBasePortOK: + Mov BasePort, AX + + Mov AL, 70h + Call PnP_ReadData ; AL[3:0] = IRQ + And AX, 15 + JZ PnP_IsolateNextCard + Mov IRQ, AX + + Mov AL, 74h + Call PnP_ReadData ; AL[2:0] = DMA + And AX, 7 + Cmp AL, 4 + JE PnP_IsolateNextCard + Mov DMA, AX + + Mov Pnp_CardFound, 1 + Jmp PnP_IsolateNextCard + +PnP_IsolateFinished: + Mov AL, PnP_CSN + ShL AL, 1 + Or AL, PnP_CardFound + + Ret + +EndP PnP_Isolate + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far ; returns carry clear if succesful + + Push CS + Pop DS + + Xor AL, AL + Mov DX, 279h + Out DX, AL + Out DX, AL + + Mov AL, 6Ah ; Starting value + Mov CX, 32 + +PnP_InitiationKeyLoop: + Out DX, AL + + Mov AH, AL + ShR AH, 1 + Xor AH, AL + ShR AX, 1 + + Dec CX + JNZ PnP_InitiationKeyLoop + +; Try three ports before concluding no PnP cards: 20Fh, 27Bh, 213h + +PnP_DetectCardPort1: + Mov PnP_ReadPort, 20Fh + Call PnP_Isolate + JZ PnP_DetectCardPort2 + Test AL, 1 + JZ PnP_DetectCardNotFound + Jmp PnP_DetectCardFound + +PnP_DetectCardPort2: + Mov PnP_ReadPort, 27Bh + Call PnP_Isolate + JZ PnP_DetectCardPort3 + Test AL, 1 + JZ PnP_DetectCardNotFound + Jmp PnP_DetectCardFound + +PnP_DetectCardPort3: + Mov PnP_ReadPort, 213h + Call PnP_Isolate + Test AL, 1 + JNZ PnP_DetectCardFound + +PnP_DetectCardNotFound: + StC + Jmp PnP_DetectEnd + +PnP_DetectCardFound: + ClC + +PnP_DetectEnd: ; Return PnP to wait for key state + Mov AX, 202h + Call PnP_WriteData + Mov EAX, 'Jeff' + + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetDSP Far ; AX = Port + + Push AX + Push CX + Push DX + + Mov DX, CS:MIDIPort + Inc DX + Mov AL, 0FFh + Out DX, AL + + Mov DX, CS:BasePort + Add DL, 6 + Mov AL, 3 + Out DX, AL + + In AL, DX + In AL, DX + In AL, DX + In AL, DX + + Xor AL, AL + Out DX, AL + + Add DL, 8 + Mov CX, 200 + +ResetDSP1: + In AL, DX + Test AL, AL + JS ResetDSP2 + Loop ResetDSP1 + Jmp ResetDSP3 + +ResetDSP2: + Sub DL, 4 + In AL, DX + Cmp AL, 0AAh + JE ResetDSP4 + Add DL, 4 + Loop ResetDSP1 + +ResetDSP3: + StC + +ResetDSP4: + Pop DX + Pop CX + Pop AX + Ret + +EndP ResetDSP + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixModeTable Label Word + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + +Proc MixSamples ; Given DS:SI = info tables, CX = numchannels + + ; 1. Clean buffer + ; + update variables + ; 2. Update parameters + ; 3. Mix func + ; 4. Return + + Push CX + + Mov CX, BytesToMix + Mov ES, MixSegment + Mov DI, MIXTABLESIZE + Xor EAX, EAX + Mov DX, CX + Add CX, CX + + Mov MixTransferOffset, DI ; } Memory write + + Cmp Stereo, 0 + JE MixSamples1 + + Mov DX, CX + +MixSamples1: + Rep StosD ; } Memory write + Mov MixTransferRemaining, DX ; } + + Pop CX + +MixSamples2: + Test Byte Ptr [SI], 1 + JZ MixSamplesEnd2 + Cmp Byte Ptr [SI+36h], 100 + JE MixSamplesEnd2 + + Push CX + Mov CX, [SI] + + Test CH, 2 + JZ MixSamples3 + And Byte Ptr [SI], Not 1 + + Jmp MixSamplesEnd +; Cmp MixMode, 8 ; Is it volume ramping? +; JB MixSamplesEnd + +MixSamples3: + Test CL, 20h ; New freq? + JZ MixSamples5 + + Mov AX, [SI+10h] + Mov DX, [SI+12h] + Mov BX, MixSpeed + Cmp DX, BX + JAE MixSamplesHandleError + + Div BX + ShL EAX, 16 + Xor AX, AX + Div BX + Mov STEPVALUE, EAX + +MixSamples4: + Test CH, 1 + JZ MixSamples5 + + Mov DWord Ptr [SI+1Ch], 0 ; Current Volume = 0 + ; for volume sliding. +MixSamples5: + Test CX, 8440h ; New volume or panning? + JZ MixSamplesMix + + Xor AX, AX + Test CH, 8 ; Muted? + JNZ MixModeCommon + + Mov BX, MixMode + Add BL, Stereo + Add BX, BX + Jmp [CS:MixModeTable+BX] + +Mix0Mode: ; 16-bit mixing, no interpolation +Mix0ModeMono: ; and 16-bit mixing, interpolation + Mov AL, [SI+20h] + ShR AL, 1 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 30 ; Use left only-mixing for mono + Jmp MixModeCommon + +Mix0ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix0ModeSurround + + Mul Byte Ptr [SI+20h] ; Final volume + Add AX, 64 + ShR AX, 7 + Mov [SI+0Ch], AX ; Store into right volume + + Mov AL, 64 + Sub AL, [SI+37h] + Mul Byte Ptr [SI+20h] + Add AX, 64 + ShR AX, 7 + Mov [SI+0Eh], AX ; Left volume + + Mov CH, AL ; CH = left volume + Mov CL, [SI+0Ch] ; CL = right volume + Mov AX, 0 + + Test CX, CX + JZ MixModeCommon + + Mov AL, 30 ; Left only... + Test CL, CL + JZ MixModeCommon + + Mov AL, 60 + Test CH, CH + JZ MixModeCommon + + Mov AL, 90 + Cmp CL, CH + JZ MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix0ModeSurround: + Mov AL, [SI+20h] + ShR AL, 2 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 150 ; Surround + Jmp MixModeCommon + +Mix6ModeMono: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 8 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Test AX, AX + JZ MixModeCommon + Mov AX, 30 + Jmp MixModeCommon + +Mix6ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix6ModeSurround + + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Ch], AX ; Store into right volume + Mov BX, AX + ShL EAX, 16 + + Mov AL, 64 ; Do left volume + Sub AL, [SI+37h] ; AL = 64-FinalPan + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Eh], AX + + Mov ECX, EAX + + ; BX = right volume + ; CX = Left volume + Mov AX, 0 + Test ECX, ECX + JZ MixModeCommon + + Mov AL, 30 + Test BX, BX + JZ MixModeCommon + + Mov AL, 60 + Test CX, CX + JZ MixModeCommon + + Mov AL, 90 + Cmp CX, BX + JE MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix6ModeSurround: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 9 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + JZ MixModeCommon + Mov AX, 150 + Jmp MixModeCommon + +MixModeCommon: ; Requires AX = 30/60/90 etc. depending + ; On mixing mode type. + ; This will add 180 for 16-bit, + ; And sort out loop types. + Mov BL, [SI+0Ah] + Test Byte Ptr [SI+18h], 2 ; 16 bit? + JZ MixModeCommon1 + + Add AX, 180 + +MixModeCommon1: + Cmp BL, 8 + JB MixModeCommon3 ; No loop + JE MixModeCommon2 ; Forwards loop + + Add AX, 10 + +MixModeCommon2: + Add AX, 10 + +MixModeCommon3: + Add AX, Offset MixFunctionTables + Add AX, MixModeOffset + Mov [SI+8], AX ; Offset... + +MixSamplesMix: + Mov BX, [SI+8] ; BX = offset into + Mov EAX, [CS:BX+2] + Mov DWord Ptr PreMixFunction, EAX + Mov EAX, [CS:BX+6] + Mov DWord Ptr MixFunctionSeparateBackwards, EAX + + Mov AX, BytesToMix + Mov MixBlockSize, AX + Mov MixBufferOffset, MIXTABLESIZE + + Mov EAX, CURRENTPOSITION + Mov OLDPOSITION, EAX + + Call Word Ptr [CS:BX] + + And Word Ptr [SI], 0111100010001101b + Jmp MixSamplesEnd + +MixSamplesHandleError: + Mov Word Ptr [SI], 200h + + Test Byte Ptr [SI+3Ah], 80h + JNZ MixSamplesEnd + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Turn off channel + +MixSamplesEnd: + Pop CX + +MixSamplesEnd2: + Add SI, 128 + Dec CX + JNZ MixSamples2 + + Ret + +EndP MixSamples + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc CheckMIDI + + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Xor BX, BX + Call UARTIn + Mov BL, [MIDIBufferTail] + + Cmp AL, 0F0h + JAE CheckMIDIEnd + + Inc BL + Cmp BL, MIDIBufferHead + JE CheckMIDIEnd + + Mov [MIDIBuffer+BX], AL + Mov [MIDIBufferTail], BL + +CheckMIDIEnd: + Pop DS + Ret + +EndP CheckMIDI + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ESSIRQHandler + + PushAD + Push DS + Push ES + + ClD + + Mov AX, CS + Mov DS, AX + Assume DS:Driver + + Mov DX, [ConfigPort] + Add DL, 6 + In AL, DX + Test AL, 8 + JZ ESSNoMIDI + + Push AX + Call CheckMIDI + Pop AX + +ESSNoMIDI: + Test AL, 1 + JZ ESSIRQEnd + + Mov DX, [BasePort] + Add DL, 0Eh + In AL, DX + + Mov AX, MixBufferPos + Mov BX, AX + Mul DMASize + Cmp AX, DMABUFFERLENGTH + JB ESSIRQHandler2 + + Xor AX, AX + Xor BX, BX + +ESSIRQHandler2: + Inc BX + Mov MixBufferPos, BX + + CLD + + + ; OK... time to get next block + ; Check whether stereo thing is on.. + ; + LES DI, [ActualDMAPtr] + Add DI, AX + + Mov BX, DMASize ; BX = bytes required + ShR BX, 1 + ; BX = samples required + Mov BP, 8 ; Skip for mono + Mov CL, 14 ; Shift for mono + + Cmp Stereo, 0 + JE ESSIRQHandlerMono + + Mov BP, 4 ; Stereo skip value. + Dec CL + +ESSIRQHandlerMono: + Call SaveEMSPageFrame + + Cmp MixTransferRemaining, 0 + JNE ESSIRQHandler4 + Assume DS:Nothing + +ESSIRQHandler3: + Push BX + Push CX + Push BP + Push ES + Push DI + + Call Update + Call MixSamples + + Pop DI + Pop ES + Pop BP + Pop CX + Pop BX + +ESSIRQHandler4: + Mov DS, MixSegment + Mov SI, MixTransferOffset + Mov DX, BX ; DX = samples to transfer + Cmp DX, MixTransferRemaining + JBE ESSIRQHandler5 + + Mov DX, MixTransferRemaining + +ESSIRQHandler5: + Push DX + Cmp CS:Filter, 1 + JB ESSIRQHandler6 + JE ESSIRQHFilter + + Cmp CS:Stereo, 0 + JE ESSIRQ3QFilterMono + +ESSIRQ3QFilterStereo: + Push BX + + Mov EBX, FilterValue + Mov EBP, FilterValue2 + ShR DX, 1 + +ESSIRQ3QFilterStereo1: + Mov EAX, EBX + Mov ECX, EBP + Add EAX, [SI] + Add ECX, [SI+4] + SAR EAX, 1 + SAR ECX, 1 + Add EBX, EAX + Add EBP, ECX + SAR EBX, 1 + SAR EBP, 1 + + Mov EAX, EBX + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSS3QFilterStereoClip1 + Cmp EAX, 7FFFh + JG WSS3QFilterStereoClip2 + +ESSIRQ3QFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSS3QFilterStereoClip3 + Cmp EAX, 7FFFh + JG WSS3QFilterStereoClip4 + +ESSIRQ3QFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ ESSIRQ3QFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp WSSMixTransferEnd + +ESSIRQ3QFilterMono: + Push BX + + Mov EBX, FilterValue + +ESSIRQ3QFilterMono1: + Mov EAX, EBX + Add EAX, [SI] + SAR EAX, 1 + Add EBX, EAX + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL WSS3QFilterMonoClip1 + Cmp EAX, 7FFFh + JG WSS3QFilterMonoClip2 + +ESSIRQ3QFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ ESSIRQ3QFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp WSSMixTransferEnd + +ESSIRQHFilter: + Cmp CS:Stereo, 0 + JE ESSIRQHFilterMono + +ESSIRQHFilterStereo: + Push BX + + Mov EBX, FilterValue + Mov EBP, FilterValue2 + ShR DX, 1 + +ESSIRQHFilterStereo1: + Add EBX, [SI] + Add EBP, [SI+4] + + SAR EBX, 1 + SAR EBP, 1 + + Mov EAX, EBX + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSSHFilterStereoClip1 + Cmp EAX, 7FFFh + JG WSSHFilterStereoClip2 + +ESSIRQHFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSSHFilterStereoClip3 + Cmp EAX, 7FFFh + JG WSSHFilterStereoClip4 + +ESSIRQHFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ ESSIRQHFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp WSSMixTransferEnd + +ESSIRQHFilterMono: + Push BX + + Mov EBX, FilterValue + +ESSIRQHFilterMono1: + Add EBX, [SI] + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL WSSHFilterMonoClip1 + Cmp EAX, 7FFFh + JG WSSHFilterMonoClip2 + +ESSIRQHFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ ESSIRQHFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp WSSMixTransferEnd + +ESSIRQHandler6: + Mov EAX, [SI] + SAR EAX, CL + + Cmp EAX, -8000h + JL ESSIRQHandlerClip1 + Cmp EAX, 7FFFh + JG ESSIRQHandlerClip2 + +ESSIRQHandler7: + StosW ; } Memory write + + Add SI, BP + Dec DX + JNZ ESSIRQHandler6 + +WSSMixTransferEnd: + Pop DX + + Sub MixTransferRemaining, DX ; } Memory write + Sub BX, DX + JNZ ESSIRQHandler3 + + Mov MixTransferOffset, SI ; } Memory write + + Call RestoreEMSPageFrame + +ESSIRQEnd: + Mov AL, 20h + Cmp IRQ, 8 + JB WSSAckIRQ1 + + Out 0A0h, AL + +WSSAckIRQ1: + Out 20h, AL + + Pop ES + Pop DS + PopAD + IRet + +ESSIRQHandlerClip1: + Mov AX, 8000h + Jmp ESSIRQHandler7 + +ESSIRQHandlerClip2: + Mov AX, 7FFFh + Jmp ESSIRQHandler7 + +WSSHFilterMonoClip1: + Mov AX, 8000h + Jmp ESSIRQHFilterMono2 + +WSSHFilterMonoClip2: + Mov AX, 7FFFh + Jmp ESSIRQHFilterMono2 + +WSSHFilterStereoClip1: + Mov AX, 8000h + Jmp ESSIRQHFilterStereo2 + +WSSHFilterStereoClip2: + Mov AX, 7FFFh + Jmp ESSIRQHFilterStereo2 + +WSSHFilterStereoClip3: + Mov AX, 8000h + Jmp ESSIRQHFilterStereo3 + +WSSHFilterStereoClip4: + Mov AX, 7FFFh + Jmp ESSIRQHFilterStereo3 + +WSS3QFilterMonoClip1: + Mov AX, 8000h + Jmp ESSIRQ3QFilterMono2 + +WSS3QFilterMonoClip2: + Mov AX, 7FFFh + Jmp ESSIRQ3QFilterMono2 + +WSS3QFilterStereoClip1: + Mov AX, 8000h + Jmp ESSIRQ3QFilterStereo2 + +WSS3QFilterStereoClip2: + Mov AX, 7FFFh + Jmp ESSIRQ3QFilterStereo2 + +WSS3QFilterStereoClip3: + Mov AX, 8000h + Jmp ESSIRQ3QFilterStereo3 + +WSS3QFilterStereoClip4: + Mov AX, 7FFFh + Jmp ESSIRQ3QFilterStereo3 + +EndP ESSIRQHandler + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Add DI, Offset IRQData + Mov BX, [CS:DI] + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset ESSIRQHandler + + XChg [ES:BX], EAX + Mov OldESSIRQHandler, EAX + + Mov AX, IMR + And AX, [DI+2] + + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Pop ES + PopAD + + Ret + +EndP SetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Mov BX, [IRQData+DI] + + Mov EAX, OldESSIRQHandler + Mov [ES:BX], EAX + + Pop ES + PopAD + + Ret + +EndP ResetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetESSMixConst + + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, CmdLineMixSpeed + Mov CX, MixSpeed + Test AX, AX + JZ GetESSMixConst1 + + Mov CX, 22050 + Cmp AX, CX + JB GetESSMixConst1 + + Mov CX, 56821 + Cmp AX, CX + JA GetESSMixConst1 + + Mov CX, AX + +GetESSMixConst1: ; CX = mixspeed. + Mov DX, 0Ch + Mov AX, 236Ch ; DX:AX = 795.5kHz + Div CX + + Mov BX, AX + Neg AL + Mov ESSMixConst, AL + + Mov DX, 0Ch + Mov AX, 236Ch + Div BX + Mov MixSpeed, AX + + Pop DS + PopA + Ret + +EndP GetESSMixConst + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StartESS + + PushA + Push ES + Push DS + + Push CS + Pop DS + Assume DS:Driver + + ; Setup DMA + Mov BX, DMASegment + Xor AX, AX + Mov DX, DMA + Mov DI, DMABUFFERLENGTH + Call SetDMA + + LES DI, ActualDMAPtr + Xor AX, AX + Mov CX, DMABUFFERLENGTH/2 + Rep StosW + + Mov MixBufferPos, 0 + Mov MixTransferRemaining, 0 + + Call ResetDSP + Mov DX, BasePort + Add DL, 0Ch + +; Extended Functions + + Mov AL, 0C6h + Call ESSOut + +; Autoinit DMA + + Mov AL, 0B8h + Call ESSOut + Mov AL, 4 + Call ESSOut + +; Stereo/Mono select + + Mov AH, 0A8h + Call ESSReadRegister + Mov AH, AL + Mov AL, 0A8h + Call ESSOut + Mov AL, AH + And AL, Not 3 + Or AL, 2 + Cmp Stereo, 0 + JE StartESS1 + + Xor AL, 3 + +StartESS1: + Call ESSOut + +; DMA mode + + Mov AL, 0B9h + Call ESSOut + Mov AL, 2 + Call ESSOut + +; Mixspeed + + Mov AL, 0A1h + Call ESSOut + Mov AL, ESSMixConst + Call ESSOut + +; Filter clock divider + Mov AL, 0A2h + Call ESSOut + + Mov AL, 0FEh + Call ESSOut + +; DMA counter + Mov CX, DMASize + Neg CX + + Mov AL, 0A4h + Call ESSOut + Mov AL, CL + Call ESSOut + Mov AL, 0A5h + Call ESSOut + Mov AL, CH + Call ESSOut + +; Initialise DAC + Mov AL, 0B6h + Call ESSOut + Mov AL, 0 + Call ESSOut + +; Configure DACs + + Mov AL, 0B7h + Call ESSOut + Mov AL, 71h + Call ESSOut + + Mov AL, 0B7h + Call ESSOut + + Mov AL, 0BCh + Cmp Stereo, 0 + JNE StartESS2 + + Mov AL, 0F4h + +StartESS2: + Call ESSOut + +; IRQ configuration + Mov AL, 0B1h + Call ESSOut + Mov AL, 50h + Call ESSOut + +; DMA configuration + Mov AL, 0B2h + Call ESSOut + Mov AL, 50h + Call ESSOut + +; Enable voice + Mov AL, 0D1h + Call ESSOut + +; Start transfer + Mov AH, 0B8h + Call ESSReadRegister + Mov AH, AL + Mov AL, 0B8h + Call ESSOut + Mov AL, AH + Or AL, 1 + Call ESSOut + +; Init UART + Mov DX, MIDIPort + Inc DX + Mov AL, 3Fh ; Intelligent mode. + Out DX, AL + +; Enable MIDI IRQ + Mov DX, BasePort + Add DL, 4 + Mov AX, 4064h + Out DX, AX + + Pop DS + Pop ES + PopA + + Ret + +EndP StartESS + Assume DS:Nothing + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov SI, Offset RelocationTable + +RelocationFix: + LodsW + Test AX, AX + JZ RelocationEnd + Mov BX, AX + Mov [BX], DS + Jmp RelocationFix + + +RelocationEnd: + Call GetEMSPageFrame + Mov EMSPageFrame, AX + + In AL, 0A1h + Mov AH, AL + In AL, 21h + Mov IMR, AX + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + Mov DX, BasePort + Add DL, 4 + Mov AL, 22h + Out DX, AL + Inc DX + In AL, DX + Mov AH, AL + And AX, 0FF0h + ShR AH, 1 + ShR AL, 5 + Mov Word Ptr [VolumeTable], AX + + Call GetESSMixConst + + Mov AX, 2643 + Mul MixSpeed + Add AX, 0FFFFh + AdC DX, 2080 + + Mov BX, (DMABUFFERLENGTH*2)/16 + Add BX, DX + + ; Allocate MixSegment first + Mov AH, 48h + + Int 21h + JNC InitSound1 + +InitSoundNoMemory: + Mov SI, Offset ESSNoMemoryMsg + Ret + +InitSound1: + Mov MixSegment, AX + Add AX, DX + Mov DMASegment, AX + + Call SetIRQ + Call GetTempo + Call SetTempo + + Mov SI, Offset ESSMsg + + Mov AX, BasePort + Mov BX, IRQ + Mov CX, DMA + + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Call ResetIRQ + Call SetIRQ + + Mov SI, Offset ReInitMsg + Mov BX, 40 + Call SetInfoLine + + Mov AL, Stereo + Call SetStereo + + Pop ES + Pop DS + PopA + + Ret + +EndP ReInitSound + Assume DS:Nothing + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, IMR + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Mov AX, MixSegment + Test AX, AX + JZ UnInitSound1 + + Mov ES, AX + Mov AH, 49h ; Release MixSegment + Int 21h + + Call ResetDSP + Call ResetIRQ + +UnInitSound1: + Ret + +EndP UnInitSound + Assume DS:Nothing + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + Push CS + Pop DS + Assume DS:Driver + +Poll1: + Call [UARTBufferEmpty] + JNC PollEnd + + Xor BX, BX + + ClI + + Mov BL, MIDIBufferHead + Cmp BL, MIDIBufferTail + JZ PollEnd ; Nothing in queue + + Inc BL + Mov AL, [MIDIBuffer+BX] + Mov MIDIBufferHead, BL + + Call [UARTSend] + Jmp Poll1 + +PollEnd: + StI + + Ret + +EndP Poll + Assume DS:Nothing + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Push AX + Push BX + Push DX + + Push BX + + Mov AX, MixSpeed + Mov BX, AX + Xor DX, DX + + ShL AX, 1 + RCL DX, 1 ; DX:AX = Mixspeed*2 + + ShR BX, 1 ; BX = Mixspeed/2 + + Add AX, BX + AdC DX, 0 ; DX:AX = Mixspeed*2.5 + + Pop BX ; BX = tempo + Div BX + + Mov BytesToMix, AX + + Pop DX + Pop BX + Pop AX + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + PushA + Push DS + + Mov BX, AX ; BX = MixVolume + Mov CS:MixVolume, BX + + Mov AX, CS:MixSegment + Test AX, AX + JZ SetMixVolume2 + + Mov DS, AX + + Mov CX, MIXTABLESIZE/2 + Mov SI, MIXTABLESIZE-2; Starting point - working backwards + +SetMixVolume1: + Mov AX, CX + + Dec AX ; AH = volume, AL = wave value. + Xor DX, DX + XChg AH, DL ; DL = Volume, AX = wave value + CBW + + IMul DX ; DX:AX = Volume * Wave Value + ; Ranges -8192->8128 + + IMul BX ; DX:AX = Volume * Wave Value * Mixing Volume + ; Ranges -1048576->1040384 + + Add AX, 64 + AdC DX, 0 + + ShRD AX, DX, 7 + Mov [SI], AX + Sub SI, 2 + + Loop SetMixVolume1 + +SetMixVolume2: + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS:RecalculateAllVolumes + + Pop DS + PopA + + Ret + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Mov CS:Stereo, AL + Cmp CS:MixSegment, 0 + JE SetStereo1 + + Call ResetDSP + Call StartESS + +SetStereo1: + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include loadsam.inc + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset ESSScreenList + + ClC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far + + Xor AH, AH + Mov AL, [CS:VolumeTable+DI] + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far + + Push DS + Push DX + + Push CS + Pop DS + Assume DS:Driver + + Mov [VolumeTable+DI], AL + + Mov DX, BasePort + Add DL, 4 + Mov AL, 22h + Out DX, AL + Mov AH, [VolumeTable] + ShL AH, 4 + Or AH, [VolumeTable+1] + ShL AH, 1 + Out DX, AX + + Pop DX + Pop DS + Ret + +EndP SetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. + +StopAfterPlay DW 0 +DefaultChannels DW 64 + DW 5 Dup (0) + + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/ES1869MX.ASM b/SoundDrivers/ES1869MX.ASM new file mode 100755 index 0000000..a6c64c0 --- /dev/null +++ b/SoundDrivers/ES1869MX.ASM @@ -0,0 +1,1734 @@ +; +; ESS Technology's ES1869 AudioDrive chip. +; + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc +include mmx.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;********************************** + +PNPSERIALID EQU 0FFFFFFFFh +PNPVENDORID EQU 03007316h + +STEREOENABLED EQU 1 +DMABUFFERLENGTH EQU 8192 +MIXRESOLUTION EQU 32 ; 32 bit mixing for +OUTPUTFILTERENABLED EQU 0 + +FPSave DB 128 Dup (0) + +ESSMsg DB "ESS ES1869 AudioDrive MMX", 13 + DB "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, DMA ", 0FDh, "D", 0 + +ESSNoMemoryMsg DB "ESS ES1869 AudioDrive MMX", 13 + DB "Error: Insufficient memory", 0 + +ReinitMsg DB "ESS ES1869 AudioDrive reinitialised", 0 + +ConfigErrorMsg DB "Error saving configuration to ITES1869.MMX", 0 +ConfigOKMsg DB "Configuration saved to ITES1869.MMX", 0 + +DriverName DB "ITES1869.MMX", 0 + +ALIGN 4 +ESSMixConst DB 0, 0 + +DMASize DW 2048 ; Smaller gives better MIDI timing +ConfigPort DW 0 + +Forced DB 0 +Stereo DB 0 +MixVolume DW 0 + +BytesToMix DW 1000 + +MixSegment DW 0 + +MixTransferOffset DW 0 +MixTransferRemaining DW 0 + +CONFIGURATIONOFFSET EQU $+128 +CONFIGSIZE EQU 4 +MixMode DW 0 +MixModeOffset DW 0 + +IMR DW 0 +OldESSIRQHandler DD 0 + +IRQData Label Word + DW 20h, 1111111111111110b ; IRQ 0 + DW 24h, 1111111111111101b ; IRQ 1 + DW 28h, 1111110111111011b ; IRQ 2 + DW 2Ch, 1111111111110111b ; IRQ 3 + DW 30h, 1111111111101111b ; IRQ 4 + DW 34h, 1111111111011111b ; IRQ 5 + DW 38h, 1111111110111111b ; IRQ 6 + DW 3Ch, 1111111101111111b ; IRQ 7 + DW 1C0h, 1111111011111011b ; IRQ 8 + DW 1C4h, 1111110111111011b ; IRQ 9 + DW 1C8h, 1111101111111011b ; IRQ 10 + DW 1CCh, 1111011111111011b ; IRQ 11 + DW 1D0h, 1110111111111011b ; IRQ 12 + DW 1D4h, 1101111111111011b ; IRQ 13 + DW 1D8h, 1011111111111011b ; IRQ 14 + DW 1DCh, 0111111111111011b ; IRQ 15 + +ESSScreenList Label + DW 6 + DW Near Ptr IdleFunctionList + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr ESSHeaderLine + + DW Near Ptr DriverText + + DW Near Ptr MixModeText + DW Near Ptr MixModeButton1 ; 6 + DW Near Ptr MixModeButton2 ; + DW Near Ptr MixModeButton3 ; 8 + DW Near Ptr MixModeButton4 ; 9 + + DW 0 + +ESSHeaderLine DW 10 + DB "ESS ES1869 AudioDrive MMX Driver", 0 + +EmptyObject DW 1 + DB 0, 0 + DB 0 + DB 0 + +DriverText DW 1 + DB 22, 48 + DB 21h + DB "ESS ES1869 AudioDrive MMX Driver 1.0 for Impulse Tracker", 0 + +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +IdleFunctionList DD 0 + DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +MixModeText DW 1 + DB 2, 14 + DB 20h + DB "Mixing Mode, Playback Frequency: ", 0FDh, "DHz", 0 +MixSpeed DW 44100 + DW 0 + +MixModeButton1 DW 2 + DW 0FFFFh, 7, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment1 DW 0 + DW 0 + DW Offset SetMixMode +DriverSegment2 DW 0 + DB 3, 16, 32, 18, 8 + DB 0 + DB " MMX, Non-Interpolated", 0 + +MixModeButton2 DW 2 + DW 6, 8, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment3 DW 0 + DW 1 + DW Offset SetMixMode +DriverSegment4 DW 0 + DB 3, 19, 32, 21, 8 + DB 0 + DB " MMX, Interpolated", 0 + +MixModeButton3 DW 2 + DW 7, 9, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment5 DW 0 + DW 2 + DW Offset SetMixMode +DriverSegment6 DW 0 + DB 3, 22, 32, 24, 8 + DB 0 + DB " MMX, Volume Ramped", 0 + +MixModeButton4 DW 2 + DW 8, 0FFFFh, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment7 DW 0 + DW 3 + DW Offset SetMixMode +DriverSegment8 DW 0 + DB 3, 25, 32, 27, 8 + DB 0 + DB " MMX, Filtered", 0 + +ALIGN 4 + +VolumeTable DB 2 Dup (0) +MIDIPort DW 0 + +MIDIBuffer DB 256 Dup (0) +MIDIBufferHead DB 0 +MIDIBufferTail DB 0 + +; ÄÄ MixingRoutines ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixBufferPos DW 0 + +include dma.inc +include mix.inc + +include m32bitm.mix +include m32bitmi.mix +include m32bitmv.mix +include m32bitmf.mix + +ALIGN 2 + +MixFunctionTables Label + +include m32bitm.inc +include m32bitmi.inc +include m32bitmv.inc +include m32bitmf.inc +include mnomix.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +RelocationTable Label Word + DW Offset DriverSegment1, Offset DriverSegment2 + DW Offset DriverSegment3, Offset DriverSegment4 + DW Offset DriverSegment5, Offset DriverSegment6 + DW Offset DriverSegment7, Offset DriverSegment8 + DW 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ESSOut ; AL = data + ; DX = 2xCh + + Push AX + +ESSOut1: + In AL, DX + Test AL, AL + JS ESSOut1 + + Pop AX + Out DX, AL + + Ret + +EndP ESSOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ESSIn ; DX = 2xCh, returns AL + +ESSIn1: + In AL, DX + Test AL, 40h + JZ ESSIn1 + + Add DL, 0Ah-0Ch ; DX = 2xAh -> Data read port + In AL, DX + Add DL, 0Ch-0Ah + + Ret + +EndP ESSIn + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UARTOut ; AL = out + + Push DX + Push AX + + Mov DX, CS:MIDIPort + Inc DX + +UARTOut1: + In AL, DX + Test AL, 40h + JNZ UARTOut1 + + Pop AX + Dec DX + Out DX, AL + + Pop DX + Ret + +EndP UARTOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UARTIn ; returns AL + + Push DX + + Mov DX, CS:MIDIPort + Inc DX + +UARTIn1: + In AL, DX + Test AL, 80h + JNZ UARTIn1 + + Dec DX + In AL, DX + + Pop DX + Ret + +EndP UARTIn + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ESSReadRegister ; AH = register to read. + ; DX = 2xCh + ; returns AL + + Mov AL, 0C0h + Call ESSOut + Mov AL, AH + Call ESSOut + Call ESSIn + + Ret + +EndP ESSReadRegister + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixMode Far + + Push CS + Pop ES + Mov DI, Offset MixMode + + Ret + +EndP GetMixMode + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixMode Far + + Mov AX, [SI+22] + + ClI + + Mov CS:MixMode, AX + + Mov BX, 60 + Mul BX + Mov CS:MixModeOffset, AX + + StI + + Mov AX, 1 + Ret + +EndP SetMixMode + Assume DS:Nothing + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +PnP_SerialID DD 0 +PnP_VendorID DD 0 +PnP_ReadPort DW 0 +PnP_CSN DB 0 +PnP_CardFound DB 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_Delay + Assume DS:Driver + + Push AX CX + + Mov CX, 180h +PnP_Delay1: + In AL, 21h + Loop PnP_Delay1 + + Pop CX AX + Ret + +EndP PnP_Delay + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_WriteData + + Mov DX, 279h + Out DX, AL + + Mov AL, AH + Mov DH, 0Ah + Out DX, AL + Ret + +EndP PnP_WriteData + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_ReadData + + Mov DX, 279h + Out DX, AL + + Mov DX, PnP_ReadPort + In AL, DX + + Ret + +EndP PnP_ReadData + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_Isolate + + Mov AX, 402h + Call Pnp_WriteData ; Reset CSNs + +PnP_IsolateNextCard: + Mov AX, 0003h + Call PnP_WriteData ; Wake[0] + + Mov AX, PnP_ReadPort + ShL AX, 6 + Xor AL, AL + Call PnP_WriteData ; Set Read Data port. + + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + + Mov AL, 1 ; Serial Isolation + Mov DX, 279h + Out DX, AL + + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + + Mov BL, 6Ah + Mov CX, 64 + Mov DX, PnP_ReadPort + + ClI + +PnP_Isolate1: + ShR PnP_SerialID, 1 + RCR PnP_VendorID, 1 + + Mov BH, BL + ShR BH, 1 + Xor BH, BL + ShR BX, 1 + + In AL, DX + Mov AH, AL + Call PnP_Delay + In AL, DX + Call PnP_Delay + + Cmp AX, 55AAh + JNE PnP_Isolate2 + + Xor BL, 80h + Or PnP_SerialID, 80000000h + +PnP_Isolate2: + Dec CX + JNZ PnP_Isolate1 + + Mov CX, 8 + Xor BH, BH + +PnP_Isolate3: + ShR BH, 1 + + In AL, DX + Mov AH, AL + Call PnP_Delay + In AL, DX + Call PnP_Delay + Cmp AX, 55AAh + JNE PnP_Isolate4 + + Or BH, 80h + +PnP_Isolate4: + Dec CX + JNZ PnP_Isolate3 + + StI + + Cmp BL, BH ; Matching Checksum? + JNE PnP_IsolateFinished + + ; assign CSN + Inc PnP_CSN + + Mov AL, 6 + MOv AH, PnP_CSN + Call PnP_WriteData + +; Cmp PnP_VendorID, PNPVENDORID +; JNE PnP_IsolateNextCard + Cmp PnP_SerialID, PNPSERIALID + JNE PnP_IsolateNextCard + + Mov AL, 3 + Call PnP_WriteData + + Mov AX, 07h ; Configuration device + Call PnP_WriteData + + Mov AL, 60h + Call PnP_ReadData + Mov AH, AL + Mov AL, 61h + Call PnP_ReadData ; AX = address. + Mov ConfigPort, AX + + Mov AX, 107h ; Audio device + Call PnP_WriteData + + Mov AL, 64h + Call PnP_ReadData + Mov AH, AL + Mov AL, 65h + Call PnP_ReadData ; AX = address. + Mov MIDIPort, AX + + Mov AL, 60h + Call PnP_ReadData + Mov AH, AL + Mov AL, 61h + Call PnP_ReadData ; AX = address. + Cmp BasePort, 0FFFFh + JE PnPBasePortOK + + Cmp BasePort, AX + JNE PnP_IsolateNextCard + +PnPBasePortOK: + Mov BasePort, AX + + Mov AL, 70h + Call PnP_ReadData ; AL[3:0] = IRQ + And AX, 15 + JZ PnP_IsolateNextCard + Mov IRQ, AX + + Mov AL, 74h + Call PnP_ReadData ; AL[2:0] = DMA + And AX, 7 + Cmp AL, 4 + JE PnP_IsolateNextCard + Mov DMA, AX + + Mov Pnp_CardFound, 1 + Jmp PnP_IsolateNextCard + +PnP_IsolateFinished: + Mov AL, PnP_CSN + ShL AL, 1 + Or AL, PnP_CardFound + + Ret + +EndP PnP_Isolate + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far ; returns carry clear if succesful + + Push CS + Pop DS + + Xor AL, AL + Mov DX, 279h + Out DX, AL + Out DX, AL + + Mov AL, 6Ah ; Starting value + Mov CX, 32 + +PnP_InitiationKeyLoop: + Out DX, AL + + Mov AH, AL + ShR AH, 1 + Xor AH, AL + ShR AX, 1 + + Dec CX + JNZ PnP_InitiationKeyLoop + +; Try three ports before concluding no PnP cards: 20Fh, 27Bh, 213h + +PnP_DetectCardPort1: + Mov PnP_ReadPort, 20Fh + Call PnP_Isolate + JZ PnP_DetectCardPort2 + Test AL, 1 + JZ PnP_DetectCardNotFound + Jmp PnP_DetectCardFound + +PnP_DetectCardPort2: + Mov PnP_ReadPort, 27Bh + Call PnP_Isolate + JZ PnP_DetectCardPort3 + Test AL, 1 + JZ PnP_DetectCardNotFound + Jmp PnP_DetectCardFound + +PnP_DetectCardPort3: + Mov PnP_ReadPort, 213h + Call PnP_Isolate + Test AL, 1 + JNZ PnP_DetectCardFound + +PnP_DetectCardNotFound: + StC + Jmp PnP_DetectEnd + +PnP_DetectCardFound: + ClC + +PnP_DetectEnd: ; Return PnP to wait for key state + Mov AX, 202h + Call PnP_WriteData + Mov EAX, 'Jeff' + + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetDSP Far ; AX = Port + + Push AX + Push CX + Push DX + + Mov DX, CS:MIDIPort + Inc DX + Mov AL, 0FFh + Out DX, AL + + Mov DX, CS:BasePort + Add DL, 6 + Mov AL, 3 + Out DX, AL + + In AL, DX + In AL, DX + In AL, DX + In AL, DX + + Xor AL, AL + Out DX, AL + + Add DL, 8 + Mov CX, 200 + +ResetDSP1: + In AL, DX + Test AL, AL + JS ResetDSP2 + Loop ResetDSP1 + Jmp ResetDSP3 + +ResetDSP2: + Sub DL, 4 + In AL, DX + Cmp AL, 0AAh + JE ResetDSP4 + Add DL, 4 + Loop ResetDSP1 + +ResetDSP3: + StC + +ResetDSP4: + Pop DX + Pop CX + Pop AX + Ret + +EndP ResetDSP + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include mmxmsam.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc CheckMIDI + + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Xor BX, BX + Call UARTIn + Mov BL, [MIDIBufferTail] + + Cmp AL, 0F0h + JAE CheckMIDIEnd + + Inc BL + Cmp BL, MIDIBufferHead + JE CheckMIDIEnd + + Mov [MIDIBuffer+BX], AL + Mov [MIDIBufferTail], BL + +CheckMIDIEnd: + Pop DS + Ret + +EndP CheckMIDI + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ESSIRQHandler + + PushAD + Push DS + Push ES + + ClD + + Mov AX, CS + Mov DS, AX + Assume DS:Driver + + Mov DX, [ConfigPort] + Add DL, 6 + In AL, DX + Test AL, 8 + JZ ESSNoMIDI + + Push AX + Call CheckMIDI + Pop AX + +ESSNoMIDI: + Test AL, 1 + JZ ESSIRQEnd + + Mov DX, [BasePort] + Add DL, 0Eh + In AL, DX + + Mov AX, MixBufferPos + Mov BX, AX + Mul DMASize + Cmp AX, DMABUFFERLENGTH + JB ESSIRQHandler2 + + Xor AX, AX + Xor BX, BX + +ESSIRQHandler2: + FNSave [FPSave] + + Inc BX + Mov MixBufferPos, BX + + CLD + + + ; OK... time to get next block + ; Check whether stereo thing is on.. + ; + LES DI, [ActualDMAPtr] + Add DI, AX + + Mov BX, DMASize ; BX = bytes required + ShR BX, 1 + ; BX = samples required + Mov BP, 8 ; Skip for mono + Mov CL, 14 ; Shift for mono + + Cmp Stereo, 0 + JE ESSIRQHandlerMono + + Mov BP, 4 ; Stereo skip value. + Dec CL + +ESSIRQHandlerMono: + Call SaveEMSPageFrame + + Cmp MixTransferRemaining, 0 + JNE ESSIRQHandler4 + Assume DS:Nothing + +ESSIRQHandler3: + Push BX + Push CX + Push BP + Push ES + Push DI + + Call Update + Call MixSamples + + Pop DI + Pop ES + Pop BP + Pop CX + Pop BX + +ESSIRQHandler4: + Mov DS, MixSegment + Mov SI, MixTransferOffset + Mov DX, BX ; DX = samples to transfer + Cmp DX, MixTransferRemaining + JBE ESSIRQHandler5 + + Mov DX, MixTransferRemaining + +ESSIRQHandler5: + +include mmxtrans.inc + + Sub MixTransferRemaining, DX ; } Memory write + Sub BX, DX + JNZ ESSIRQHandler3 + + Mov MixTransferOffset, SI ; } Memory write + + Call RestoreEMSPageFrame + + FNRStor [CS:FPSave] + +ESSIRQEnd: + Mov AL, 20h + Cmp IRQ, 8 + JB WSSAckIRQ1 + + Out 0A0h, AL + +WSSAckIRQ1: + Out 20h, AL + + Pop ES + Pop DS + PopAD + IRet + +EndP ESSIRQHandler + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Add DI, Offset IRQData + Mov BX, [CS:DI] + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset ESSIRQHandler + + XChg [ES:BX], EAX + Mov OldESSIRQHandler, EAX + + Mov AX, IMR + And AX, [DI+2] + + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Pop ES + PopAD + + Ret + +EndP SetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Mov BX, [IRQData+DI] + + Mov EAX, OldESSIRQHandler + Mov [ES:BX], EAX + + Pop ES + PopAD + + Ret + +EndP ResetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetESSMixConst + + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, CmdLineMixSpeed + Mov CX, MixSpeed + Test AX, AX + JZ GetESSMixConst1 + + Mov CX, 22050 + Cmp AX, CX + JB GetESSMixConst1 + + Mov CX, 56821 + Cmp AX, CX + JA GetESSMixConst1 + + Mov CX, AX + +GetESSMixConst1: ; CX = mixspeed. + Mov DX, 0Ch + Mov AX, 236Ch ; DX:AX = 795.5kHz + Div CX + + Mov BX, AX + Neg AL + Mov ESSMixConst, AL + + Mov DX, 0Ch + Mov AX, 236Ch + Div BX + Mov MixSpeed, AX + + FNInit + FILd DWord Ptr [MixSpeed] + FMul FreqMultiplier + FStP FreqMultiplier + + Pop DS + PopA + Ret + +EndP GetESSMixConst + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StartESS + + PushA + Push ES + Push DS + + Push CS + Pop DS + Assume DS:Driver + + ; Setup DMA + Mov BX, MixSegment + Mov AX, 80 + Mov DX, DMA + Mov DI, DMABUFFERLENGTH + Call SetDMA + + LES DI, ActualDMAPtr + Xor AX, AX + Mov CX, DMABUFFERLENGTH/2 + Rep StosW + + Mov MixBufferPos, 0 + Mov MixTransferRemaining, 0 + + Call ResetDSP + Mov DX, BasePort + Add DL, 0Ch + +; Extended Functions + + Mov AL, 0C6h + Call ESSOut + +; Autoinit DMA + + Mov AL, 0B8h + Call ESSOut + Mov AL, 4 + Call ESSOut + +; Stereo/Mono select + + Mov AH, 0A8h + Call ESSReadRegister + Mov AH, AL + Mov AL, 0A8h + Call ESSOut + Mov AL, AH + And AL, Not 3 + Or AL, 2 + Cmp Stereo, 0 + JE StartESS1 + + Xor AL, 3 + +StartESS1: + Call ESSOut + +; DMA mode + + Mov AL, 0B9h + Call ESSOut + Mov AL, 2 + Call ESSOut + +; Mixspeed + + Mov AL, 0A1h + Call ESSOut + Mov AL, ESSMixConst + Call ESSOut + +; Filter clock divider + Mov AL, 0A2h + Call ESSOut + + Mov AL, 0FEh + Call ESSOut + +; DMA counter + Mov CX, DMASize + Neg CX + + Mov AL, 0A4h + Call ESSOut + Mov AL, CL + Call ESSOut + Mov AL, 0A5h + Call ESSOut + Mov AL, CH + Call ESSOut + +; Initialise DAC + Mov AL, 0B6h + Call ESSOut + Mov AL, 0 + Call ESSOut + +; Configure DACs + + Mov AL, 0B7h + Call ESSOut + Mov AL, 71h + Call ESSOut + + Mov AL, 0B7h + Call ESSOut + + Mov AL, 0BCh + Cmp Stereo, 0 + JNE StartESS2 + + Mov AL, 0F4h + +StartESS2: + Call ESSOut + +; IRQ configuration + Mov AL, 0B1h + Call ESSOut + Mov AL, 50h + Call ESSOut + +; DMA configuration + Mov AL, 0B2h + Call ESSOut + Mov AL, 50h + Call ESSOut + +; Enable voice + Mov AL, 0D1h + Call ESSOut + +; Start transfer + Mov AH, 0B8h + Call ESSReadRegister + Mov AH, AL + Mov AL, 0B8h + Call ESSOut + Mov AL, AH + Or AL, 1 + Call ESSOut + +; Init UART + Mov DX, MIDIPort + Inc DX + Mov AL, 3Fh ; Intelligent mode. + Out DX, AL + +; Enable MIDI IRQ + Mov DX, BasePort + Add DL, 4 + Mov AX, 4064h + Out DX, AX + + Pop DS + Pop ES + PopA + + Ret + +EndP StartESS + Assume DS:Nothing + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov SI, Offset RelocationTable + +RelocationFix: + LodsW + Test AX, AX + JZ RelocationEnd + Mov BX, AX + Mov [BX], DS + Jmp RelocationFix + + +RelocationEnd: + Call GetEMSPageFrame + Mov EMSPageFrame, AX + + In AL, 0A1h + Mov AH, AL + In AL, 21h + Mov IMR, AX + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + Mov DX, BasePort + Add DL, 4 + Mov AL, 22h + Out DX, AL + Inc DX + In AL, DX + Mov AH, AL + And AX, 0FF0h + ShR AH, 1 + ShR AL, 5 + Mov Word Ptr [VolumeTable], AX + + Call GetESSMixConst + + Mov AX, 2643 + Mul MixSpeed + Add AX, 0FFFFh + AdC DX, (DMABUFFERLENGTH*2)/16+5 + Mov BX, DX + Mov AH, 48h + + Int 21h + JNC InitSound1 + +InitSoundNoMemory: + Mov SI, Offset ESSNoMemoryMsg + Ret + +InitSound1: + Mov MixSegment, AX + + Call SetIRQ + Call GetTempo + Call SetTempo + + Mov SI, Offset ESSMsg + + Mov AX, BasePort + Mov BX, IRQ + Mov CX, DMA + + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Call ResetIRQ + Call SetIRQ + + Mov SI, Offset ReInitMsg + Mov BX, 40 + Call SetInfoLine + + Mov AL, Stereo + Call SetStereo + + Pop ES + Pop DS + PopA + + Ret + +EndP ReInitSound + Assume DS:Nothing + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Call GotoHomeDirectory + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, 3D02h ; Read write access + Mov DX, Offset DriverName + Int 21h + JC SaveConfig2 + + Mov BX, AX + + Mov AX, 4200h + Xor CX, CX + Mov DX, Offset CONFIGURATIONOFFSET + Int 21h + JC SaveConfig1 + + Mov AH, 40h + Mov CX, CONFIGSIZE + Mov DX, Offset MixMode + Int 21h + +SaveConfig1: + Mov AH, 3Eh + Int 21h + +SaveConfig2: + Mov AX, IMR + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Mov AX, MixSegment + Test AX, AX + JZ UnInitSound1 + + Mov ES, AX + Mov AH, 49h ; Release MixSegment + Int 21h + + Call ResetDSP + Call ResetIRQ + +UnInitSound1: + Ret + +EndP UnInitSound + Assume DS:Nothing + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + Push CS + Pop DS + Assume DS:Driver + +Poll1: + Call [UARTBufferEmpty] + JNC PollEnd + + Xor BX, BX + + ClI + + Mov BL, MIDIBufferHead + Cmp BL, MIDIBufferTail + JZ PollEnd ; Nothing in queue + + Inc BL + Mov AL, [MIDIBuffer+BX] + Mov MIDIBufferHead, BL + + Call [UARTSend] + Jmp Poll1 + +PollEnd: + StI + + Ret + +EndP Poll + Assume DS:Nothing + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Push AX + Push BX + Push DX + + Push BX + + Mov AX, MixSpeed + Mov BX, AX + Xor DX, DX + + ShL AX, 1 + RCL DX, 1 ; DX:AX = Mixspeed*2 + + ShR BX, 1 ; BX = Mixspeed/2 + + Add AX, BX + AdC DX, 0 ; DX:AX = Mixspeed*2.5 + + Pop BX ; BX = tempo + Div BX + + Mov BytesToMix, AX + + Pop DX + Pop BX + Pop AX + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + Mov CS:MixVolume, AX + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Jmp CS:RecalculateAllVolumes + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Mov CS:Stereo, AL + Cmp CS:MixSegment, 0 + JE SetStereo1 + + Call ResetDSP + Call StartESS + +SetStereo1: + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include loadsam.inc + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset ESSScreenList + + ClC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far + + Xor AH, AH + Mov AL, [CS:VolumeTable+DI] + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far + + Push DS + Push DX + + Push CS + Pop DS + Assume DS:Driver + + Mov [VolumeTable+DI], AL + + Mov DX, BasePort + Add DL, 4 + Mov AL, 22h + Out DX, AL + Mov AH, [VolumeTable] + ShL AH, 4 + Or AH, [VolumeTable+1] + ShL AH, 1 + Out DX, AX + + Pop DX + Pop DS + Ret + +EndP SetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +InterpretState DB 0 +InterpretType DB 0 + +Proc SendUARTOut Far ; Local interpreter activated with 0F0h 0F0h. + + Mov AH, CS:InterpretState + Cmp AH, 2 + JB SendUARTOut1 + +; In interpreter. + JE SendUARTOut3 + +; Have InterpretType, now get parameter, then return to normal. + + Cmp AL, 7Fh + JA SendUARTOut4 + + Push BX + + Mov BL, CS:InterpretType ; Want BX = InterpretType*64+Channel + ; + ShL BX, 6 + Add BL, [DI+20h] + And BX, 127 + Mov [CS:FilterParameters+BX], AL + + Pop BX + + Test SI, SI + JZ SendUARTOut4 + + Or Byte Ptr [SI], 64 + +SendUARTOut4: + Mov CS:InterpretState, 0 + Ret + +SendUARTOut3: + Cmp AL, 2 + JAE SendUARTOut4 + + Mov CS:InterpretType, AL + Jmp SendUARTOutStateInc + +SendUARTOut1: + Cmp AL, 0F0h + JNE SendUARTOut2 + +SendUARTOutStateInc: + Inc CS:InterpretState + Ret + +SendUARTOut2: + Test AH, AH + JZ SendUARTOutEnd + + Push AX + Mov AL, 0F0h + Call UARTOut + Pop AX + Mov CS:InterpretState, 0 + +SendUARTOutEnd: + Cmp AL, 0FCh + JE ResetFilters + Cmp AL, 0FAh + JE ResetFilters + + Cmp AL, 0FFh + JNE SendUARTOutNoClear + +ResetFilters: + PushA + Push ES + + Push CS + Pop ES + + Mov DI, Offset FilterParameters + Mov CX, 64 + Mov AL, 7Fh + Rep StosB + Mov CX, 64 + Xor AX, AX + Rep StosB + + Pop ES + PopA + +SendUARTOutNoClear: + Call UARTOut + Ret + +EndP SendUARTOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. + +StopAfterPlay DW 0 +DefaultChannels DW 128 + DW 3 ; MIDI, hiqual + DW 4 Dup (0) + + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + DW Offset SendUARTOut + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/EWS64.ASM b/SoundDrivers/EWS64.ASM new file mode 100755 index 0000000..abd573f --- /dev/null +++ b/SoundDrivers/EWS64.ASM @@ -0,0 +1,933 @@ + + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;*********************************************** + +TRACEENABLED = 0 +CREATENEWLOGFILE = 1 + +include debug.inc + +PNPVENDORID EQU 36A8630Eh + +MMT_MAXENTRIES EQU 64 +MMT_MAXSIZE EQU 3*MMT_MAXENTRIES + +ST97Message DB "EWS 64 Synthesizer Detected", 13 +; DB "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, ", 0FDh, "Dk RAM", 0 + DB "Port ", 0FDh, "Xh, ", 0FDh, "D Voices, ", 0FDh, "Dk", 0 + +StatusLine DB "FreeEWS ", 0FDh, "Dk", 0 + +MMTData DW MMT_MAXSIZE Dup (0) + +IRQData Label Word + DW 20h, 1111111111111110b ; IRQ 0 + DW 24h, 1111111111111101b ; IRQ 1 + DW 28h, 1111110111111011b ; IRQ 2 + DW 2Ch, 1111111111110111b ; IRQ 3 + DW 30h, 1111111111101111b ; IRQ 4 + DW 34h, 1111111111011111b ; IRQ 5 + DW 38h, 1111111110111111b ; IRQ 6 + DW 3Ch, 1111111101111111b ; IRQ 7 + DW 1C0h, 1111111011111011b ; IRQ 8 + DW 1C4h, 1111110111111011b ; IRQ 9 + DW 1C8h, 1111101111111011b ; IRQ 10 + DW 1CCh, 1111011111111011b ; IRQ 11 + DW 1D0h, 1110111111111011b ; IRQ 12 + DW 1D4h, 1101111111111011b ; IRQ 13 + DW 1D8h, 1011111111111011b ; IRQ 14 + DW 1DCh, 0111111111111011b ; IRQ 15 + +; ÄÄ EmptyFunction ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc EmptyFunction Far + + Xor AX, AX + StC + Ret + +EndP EmptyFunction + +; ÄÄ ST97InString ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ST97InString ; ES:DI points to deposit point. + ; EAX = memory address + ; CX = count + + ClI + + Mov BL, 2 ; Ctrl=RD_MEM, Data=Memory Address + Call ST97OutDWord + + Mov DX, CS:BasePort ; Length + Mov AX, CX + Call ST97SendByte + + Mov AL, AH + Call ST97SendByte + +ST97InString1: + Call ST97InByte + Cmp AL, 0ABh + JE ST97InStringError + Cmp AL, 0ACh + JNE ST97InString1 + +ST97InString2: + Inc DX + Inc DX + + Rep InsW + + ClC + StI + Ret + +ST97InStringError: + StC + StI + Ret + +EndP ST97InString + +; ÄÄ ST97ReceiveByte ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ST97ReceiveByte ; Returns AL + + Push DX + Mov DX, CS:BasePort + Inc DX + +ST97ReceiveByte1: + In AL, DX + Test AL, AL + JS ST97ReceiveByte1 + + Dec DX + In AL, DX + Pop DX + + Ret + +EndP ST97ReceiveByte + +; ÄÄ ST97InByte ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ST97InByte ; Returns AL + + Jmp ST97ReceiveByte + +EndP ST97InByte + +; ÄÄ ST97InWord ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ST97InWord ; Returns AX + + ClI + + Call ST97ReceiveByte + Mov AL, AH + + Call ST97ReceiveByte + XChg AL, AH + + StI + + Ret + +EndP ST97InWord + +; ÄÄ ST97InDWord ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ST97InDWord ; Returns EAX + + ClI + + Call ST97ReceiveByte + RoR EAX, 8 + + Call ST97ReceiveByte + RoR EAX, 8 + + Call ST97ReceiveByte + RoR EAX, 8 + + Call ST97ReceiveByte + RoR EAX, 8 + + StI + Ret + +EndP ST97InDWord + +; ÄÄ ST97SendByte ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ST97SendByte ; DX = port, AL = data + + Push AX + Push DX + Mov DX, CS:BasePort + Inc DX + +ST97SendByte1: + In AL, DX + Test AL, 40h + JNZ ST97SendByte1 + + Pop DX + Pop AX + + Out DX, AL + + Ret + +EndP ST97SendByte + +; ÄÄ ST97OutByte ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ST97OutByte ; AL = data, AH = command, destroys AX + + ClI + Push DX + + Mov DX, CS:BasePort + Inc DX + + XChg AH, AL + Call ST97SendByte + + Dec DX + + Mov AL, AH + Call ST97SendByte + + Pop DX + StI + + Ret + +EndP ST97OutByte + +; ÄÄ ST97OutWord ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ST97OutWord ; AX = data, BL = command, destroys AX + + ClI + Push DX + Push AX + + Mov DX, CS:BasePort + Mov AL, BL + Inc DX + Call ST97SendByte + + Pop AX + Dec DX + Call ST97SendByte + + Mov AL, AH + Call ST97SendByte + + Pop DX + StI + + Ret + +EndP ST97OutWord + +; ÄÄ ST97OutDWord ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ST97OutDWord ; EAX = data, BL = command + + ClI + Push DX + Push AX + + Mov DX, CS:BasePort + Mov AL, BL + Inc DX + Call ST97SendByte + + Pop AX + Dec DX + Call ST97SendByte + + ShR EAX, 8 + Call ST97SendByte + + ShR EAX, 8 + Call ST97SendByte + + ShR EAX, 8 + Call ST97SendByte + + Pop DX + StI + + Ret + +EndP ST97OutDWord + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +PnP_SerialID DD 0 +PnP_VendorID DD 0 +PnP_ReadPort DW 0 +PnP_CSN DB 0 +PnP_CardFound DB 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetUART ; Given DX = Port + + ClI + + Inc DX + + Mov AL, 0FFh ; Reset! + Out DX, AL + Out DX, AL ; Two resets required to ensure it'll work + + Xor CX, CX + +ResetUART2: + In AL, DX + Test AL, 80h + JNZ ResetUART3 + + Dec DX + In AL, DX + Inc DX + Cmp AL, 0FEh + JE ResetUART4 + +ResetUART3: + Loop ResetUART2 + +ResetUARTError: + StI + StC + Ret + +ResetUART4: ; Now to shove it into 'intelligent' mode. + Xor CX, CX + +ResetUART5: + In AL, DX + Test AL, 40h + LoopNZ ResetUART5 + JNZ ResetUARTError + + Mov AL, 3Fh ; Intelligent mode! + Out DX, AL + +ResetUART6: + Xor CX, CX + +ResetUART7: + In AL, DX + Test AL, 80h + JNZ ResetUART8 + + Dec DX + In AL, DX + Inc DX + Cmp AL, 0FEh + JE ResetUART9 + +ResetUART8: + Loop ResetUART7 + Jmp ResetUARTError + +ResetUART9: + StI + ClC + Ret + +EndP ResetUART + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_Delay + Assume DS:Driver + + Push AX CX + + Mov CX, 180h +PnP_Delay1: + In AL, 21h + Loop PnP_Delay1 + + Pop CX AX + Ret + +EndP PnP_Delay + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_WriteData + + Mov DX, 279h + Out DX, AL + + Mov AL, AH + Mov DH, 0Ah + Out DX, AL + Ret + +EndP PnP_WriteData + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_ReadData + + Mov DX, 279h + Out DX, AL + + Mov DX, PnP_ReadPort + In AL, DX + + Ret + +EndP PnP_ReadData + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_Isolate + + Mov AX, 402h + Call Pnp_WriteData ; Reset CSNs + +PnP_IsolateNextCard: + Mov AX, 0003h + Call PnP_WriteData ; Wake[0] + + Mov AX, PnP_ReadPort + ShL AX, 6 + Xor AL, AL + Call PnP_WriteData ; Set Read Data port. + + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + + Mov AL, 1 ; Serial Isolation + Mov DX, 279h + Out DX, AL + + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + + Mov BL, 6Ah + Mov CX, 64 + Mov DX, PnP_ReadPort + + ClI + +PnP_Isolate1: + ShR PnP_SerialID, 1 + RCR PnP_VendorID, 1 + + Mov BH, BL + ShR BH, 1 + Xor BH, BL + ShR BX, 1 + + In AL, DX + Mov AH, AL + Call PnP_Delay + In AL, DX + Call PnP_Delay + + Cmp AX, 55AAh + JNE PnP_Isolate2 + + Xor BL, 80h + Or PnP_SerialID, 80000000h + +PnP_Isolate2: + Dec CX + JNZ PnP_Isolate1 + + Mov CX, 8 + Xor BH, BH + +PnP_Isolate3: + ShR BH, 1 + + In AL, DX + Mov AH, AL + Call PnP_Delay + In AL, DX + Call PnP_Delay + Cmp AX, 55AAh + JNE PnP_Isolate4 + + Or BH, 80h + +PnP_Isolate4: + Dec CX + JNZ PnP_Isolate3 + + StI + + Cmp BL, BH ; Matching Checksum? + JNE PnP_IsolateFinished + + ; assign CSN + Inc PnP_CSN + + Mov AL, 6 + MOv AH, PnP_CSN + Call PnP_WriteData + + Cmp PnP_VendorID, PNPVENDORID + JNE PnP_IsolateNextCard + + Mov AL, 3 + Call PnP_WriteData + Mov AX, 407h ; LDN 4 + Call PnP_WriteData + + Mov AL, 60h + Call PnP_ReadData + Mov AH, AL + Mov AL, 61h + Call PnP_ReadData ; AX = address. + Cmp BasePort, 0FFFFh + JE PnPBasePortOK + + Cmp BasePort, AX + JNE PnP_IsolateNextCard + +PnPBasePortOK: + Mov BasePort, AX + + Mov AL, 70h + Call PnP_ReadData ; AL[3:0] = IRQ + And AX, 15 + JZ PnP_IsolateNextCard + Mov IRQ, AX + + Mov Pnp_CardFound, 1 + Jmp PnP_IsolateNextCard + +PnP_IsolateFinished: + Mov AL, PnP_CSN + ShL AL, 1 + Or AL, PnP_CardFound + + Ret + +EndP PnP_Isolate + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far ; returns carry clear if succesful + + Trace "Detecting EWS64XL" + + Push CS + Pop DS + + Xor AL, AL + Mov DX, 279h + Out DX, AL + Out DX, AL + + Mov AL, 6Ah ; Starting value + Mov CX, 32 + +PnP_InitiationKeyLoop: + Out DX, AL + + Mov AH, AL + ShR AH, 1 + Xor AH, AL + ShR AX, 1 + + Dec CX + JNZ PnP_InitiationKeyLoop + +; Try three ports before concluding no PnP cards: 20Fh, 27Bh, 213h + +PnP_DetectCardPort1: + Mov PnP_ReadPort, 20Fh + Call PnP_Isolate + JZ PnP_DetectCardPort2 + Test AL, 1 + JZ PnP_DetectCardNotFound + Jmp PnP_DetectCardFound + +PnP_DetectCardPort2: + Mov PnP_ReadPort, 27Bh + Call PnP_Isolate + JZ PnP_DetectCardPort3 + Test AL, 1 + JZ PnP_DetectCardNotFound + Jmp PnP_DetectCardFound + +PnP_DetectCardPort3: + Mov PnP_ReadPort, 213h + Call PnP_Isolate + Test AL, 1 + JNZ PnP_DetectCardFound + +PnP_DetectCardNotFound: + Trace "EWS64XL Not found" + + StC + Jmp PnP_DetectEnd + +PnP_DetectCardFound: + +; Check whether the MPU can be reset + Mov DX, BasePort + Call ResetUART + JC PnP_DetectCardNotFound + +; Find memory mapping table + Mov AX, 300h ; Ctrl 3 (GET_MMT), Data 0 + Call ST97OutByte + Call ST97InDWord + + Push CS + Pop ES + Mov CX, MMT_MAXSIZE + Mov DI, Offset MMTData + Call ST97InString + + Trace "EWS64XL Found" + +PnP_DetectEnd: ; Return PnP to wait for key state + Mov AX, 202h + Call PnP_WriteData + Mov EAX, 'Jeff' + + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Trace "EWS64XL InitSound" + + Mov SI, Offset ST97Message +Comment ~ + Mov AX, BasePort + Mov BX, IRQ + Mov ECX, DWord Ptr [MMTData+2] + ShR ECX, 9 +~ + Xor BX, BX + Mov AX, 5100h ; Cntrl = GET_VOI, Data = 0 + Call ST97OutByte + Call ST97InByte + Mov BL, AL + Mov AX, BasePort + Mov ECX, DWord Ptr [MMTData+2] + ShR ECX, 9 + + Trace "EWS64XL InitSoundEnd" + + ClC + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + Ret + +EndP ReInitSound + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Mov DX, CS:BasePort + Inc DX + Mov AL, 0FFh + Out DX, AL + + Ret + +EndP UnInitSound + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + Ret + +EndP Poll + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + Ret + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load (0 based) +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc LoadSample Far + + StC + Ret + +EndP LoadSample + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release (1 based) +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + Push CS + Pop DS + Assume DS:Driver + + Mov SI, Offset MMTData+6 + Xor EAX, EAX + +GetStatus1: + Mov CX, [SI] + Add SI, 6 + + Cmp CX, -1 + JE GetStatus2 + + Cmp CX, 1 + JA GetStatus1 + JB GetStatus1 + + Add EAX, [SI+2] + Sub EAX, [SI-4] + Jmp GetStatus1 + +GetStatus2: + Mov SI, Offset StatusLine + ShR EAX, 9 + + ClC + Ret + +EndP GetStatus + Assume DS:Nothing + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Xor AX, AX + StC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far + + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far + + Ret + +EndP SetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 64 ; Maximum number of channels the + ; driver can handle. +StopAfterPlay DW 0 +DefaultChannels DW 64 + + DW 5 Dup (0) + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/EWSCODEC.ASM b/SoundDrivers/EWSCODEC.ASM new file mode 100755 index 0000000..604c014 --- /dev/null +++ b/SoundDrivers/EWSCODEC.ASM @@ -0,0 +1,3016 @@ +; +; EWS 64 Codec Driver +; + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;********************************** + +TRACEENABLED = 0 +CREATENEWLOGFILE = 1 + +include debug.inc + +STEREOENABLED EQU 1 +DMABUFFERLENGTH EQU 8192 +MIXRESOLUTION EQU 32 ; 32 bit mixing for +MIXTABLESIZE EQU 2*256*65 +DATAFLAG EQU 200h +ACKFLAG EQU 300h + +PNPSERIALID EQU 98B03C20h +PNPVENDORID EQU 36A8630Eh + +DMASize DW 4096 + +WSSMsg DB "Audiosystem EWS64 XL Codec", 13 + DB "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, DMA ", 0FDh, "D", 0 + +WSSNoMemoryMsg DB "Audiosystem EWS64 XL Codec", 13 + DB "Error: Insufficient memory", 0 + +ReinitMsg DB "Audiosystem EWS64 XL reinitialised", 0 + +DriverName DB "ITEWSCOD.DRV", 0 + +ALIGN 2 + +Forced DB 0 +Stereo DB 0 +MixVolume DW 0 + +BytesToMix DW 1000 +WSSMixConst DB 0 + +MixSegment DW 0 +DMASegment DW 0 + +MixTransferOffset DW 0 +MixTransferRemaining DW 0 + +CONFIGURATIONOFFSET EQU $+128 +CONFIGSIZE EQU 37 +MixMode DW 0 +MixModeOffset DW 0 +Filter DW 0 +VolumeTable DB 56, 56 + DB 60h, 60h, 0Ch ; Low Band + DB 40h, 40h, 1Bh ; Med Low Band + DB 40h, 40h, 72h ; Med High Band + DB 60h, 60h, 40h ; High Band + DB 0, 0, 0 ; Echo + DB 0, 2 ; Surround + DB 0, 90h, 4, 7Fh, 22h ; Reverb + DB 0, 90h, 2, 40h, 9, 3, 13h ; Chorus + +IMR DW 0 +OldWSSIRQHandler DD 0 + +; String format, Count, [Data/Port]*Count +; Port = 1 for Control port, 0 for data port. + +SAM9407Reset DW 66 + DW 1BEh, 16Fh, 7Fh, 7Fh, ACKFLAG ; Audio in on + DW 1BEh, 168h, 7Fh, 7Fh, ACKFLAG ; Echo on + DW 1BEh, 16Ch, 7Fh, 7Fh, ACKFLAG ; Reverb on + DW 1BEh, 16Dh, 7Fh, 7Fh, ACKFLAG ; Chorus on + DW 1BEh, 16Bh, 0, 0, ACKFLAG ; Equalizer type + DW 1BEh, 16Eh, 7Fh, 7Fh, ACKFLAG ; Surround on + DW 1BEh, 165h, 7Fh, 7Fh ; Post eff on Audio in + DW 1BEh, 166h, 7Fh, 7Fh ; Post eff on reverb, chorus + DW 1BEh, 133h, 0, 0 ; 2 Speaker + DW 1BEh, 120h, 7Fh, 7Fh ; Stereo input 2 + DW 1BEh, 134h, 0FFh, 0FFh ; Left gain + DW 1BEh, 135h, 0FFh, 0FFh ; Right gain + DW 1BEh, 136h, 0, 0 ; Left pan + DW 1BEh, 137h, 7Fh, 7Fh ; Right pan + DW 1BEh, 107h, 0FFh, 0FFh ; Master volume + +SAM9407EqLBL DW 4 + DW 1BEh, 110h, DATAFLAG, 60h +SAM9407EqLBR DW 4 + DW 1BEh, 114h, DATAFLAG, 60h +SAM9407EqLBF DW 4 + DW 1BEh, 118h, DATAFLAG, 0Ch +SAM9407EqMLBL DW 4 + DW 1BEh, 111h, DATAFLAG, 40h +SAM9407EqMLBR DW 4 + DW 1BEh, 115h, DATAFLAG, 40h +SAM9407EqMLBF DW 4 + DW 1BEh, 119h, DATAFLAG, 1Bh +SAM9407EqMHBL DW 4 + DW 1BEh, 112h, DATAFLAG, 40h +SAM9407EqMHBR DW 4 + DW 1BEh, 116h, DATAFLAG, 40h +SAM9407EqMHBF DW 4 + DW 1BEh, 11Ah, DATAFLAG, 72h +SAM9407EqHBL DW 4 + DW 1BEh, 113h, DATAFLAG, 60h +SAM9407EqHBR DW 4 + DW 1BEh, 117h, DATAFLAG, 60h +SAM9407EqHBF DW 4 + DW 1BEh, 11Bh, DATAFLAG, 0Ch +SAM9407EchoLevel DW 4 + DW 1BEh, 128h, DATAFLAG, 0 +SAM9407EchoTime DW 4 + DW 1BEh, 129h, DATAFLAG, 2Bh +SAM9407EchoFeed DW 4 + DW 1BEh, 12Ah, DATAFLAG, 40h +SAM9407SurroundVolume DW 4 + DW 1BEh, 130h, DATAFLAG, 0 +SAM9407SurroundDelay DW 4 + DW 1BEh, 131h, DATAFLAG, 2 +SAM9407ReverbSend DW 4 + DW 1BEh, 127h, DATAFLAG, 0 +SAM9407ReverbVolume DW 3 + DW 1BEh, 13Ah, DATAFLAG +SAM9407ReverbType DW 4 + DW 1BEh, 169h, DATAFLAG, 4 +SAM9407ReverbTime DW 3 + DW 1BEh, 178h, DATAFLAG +SAM9407ReverbFeedback DW 3 + DW 1BEh, 179h, DATAFLAG +SAM9407ChorusSend DW 4 + DW 1BEh, 124h, DATAFLAG, 0 +SAM9407ChorusVolume DW 3 + DW 1BEh, 13Bh, DATAFLAG +SAM9407ChorusType DW 4 + DW 1BEh, 16Ah, DATAFLAG, 2 +SAM9407ChorusDelay DW 3 + DW 1BEh, 174h, DATAFLAG +SAM9407ChorusFeedback DW 3 + DW 1BEh, 175h, DATAFLAG +SAM9407ChorusRate DW 3 + DW 1BEh, 176h, DATAFLAG +SAM9407ChorusDepth DW 3 + DW 1BEh, 177h, DATAFLAG +SAM9407Mono DW 4 + DW 1BEh, 132h, 7Fh, 0 +SAM9407Stereo DW 4 + DW 1BEh, 132h, 0, 0 + +SAM9407Strings DW Offset SAM9407Reset ;1 + DW Offset SAM9407EqLBL, Offset SAM9407EqLBR + DW Offset SAM9407EqLBF + DW Offset SAM9407EqMLBL, Offset SAM9407EqMLBR + DW Offset SAM9407EqMLBF + DW Offset SAM9407EqMHBL, Offset SAM9407EqMHBR + DW Offset SAM9407EqMHBF + DW Offset SAM9407EqHBL, Offset SAM9407EqHBR + DW Offset SAM9407EqHBF + DW Offset SAM9407EchoLevel ; 14 + DW Offset SAM9407EchoTime + DW Offset SAM9407EchoFeed + DW Offset SAM9407SurroundVolume ; 17 + DW Offset SAM9407SurroundDelay + DW Offset SAM9407ReverbSend ; 19 + DW Offset SAM9407ReverbVolume + DW Offset SAM9407ReverbType + DW Offset SAM9407ReverbTime + DW Offset SAM9407ReverbFeedback ; 23 + DW Offset SAM9407ChorusSend ; 24 + DW Offset SAM9407ChorusVolume + DW Offset SAM9407ChorusType + DW Offset SAM9407ChorusDelay + DW Offset SAM9407ChorusFeedback + DW Offset SAM9407ChorusRate + DW Offset SAM9407ChorusDepth ; 30 + DW Offset SAM9407Mono ; 31 + DW Offset SAM9407Stereo + + +FilterValue DD 0 +FilterValue2 DD 0 + +MixSpeedTable DW 5513, 41h + DW 6615, 4Fh + DW 8000, 40h + DW 9600, 4Eh + DW 11025, 43h + DW 16000, 42h + DW 18900, 45h + DW 22050, 47h + DW 27429, 44h + DW 32000, 46h + DW 33075, 4Dh + DW 37800, 49h + DW 44100, 4Bh + DW 48000, 4Ch + +IRQData Label Word + DW 20h, 1111111111111110b ; IRQ 0 + DW 24h, 1111111111111101b ; IRQ 1 + DW 28h, 1111110111111011b ; IRQ 2 + DW 2Ch, 1111111111110111b ; IRQ 3 + DW 30h, 1111111111101111b ; IRQ 4 + DW 34h, 1111111111011111b ; IRQ 5 + DW 38h, 1111111110111111b ; IRQ 6 + DW 3Ch, 1111111101111111b ; IRQ 7 + DW 1C0h, 1111111011111011b ; IRQ 8 + DW 1C4h, 1111110111111011b ; IRQ 9 + DW 1C8h, 1111101111111011b ; IRQ 10 + DW 1CCh, 1111011111111011b ; IRQ 11 + DW 1D0h, 1110111111111011b ; IRQ 12 + DW 1D4h, 1101111111111011b ; IRQ 13 + DW 1D8h, 1011111111111011b ; IRQ 14 + DW 1DCh, 0111111111111011b ; IRQ 15 + +;********************************** +; WSS Registers +;********************************** + +CODEC_INDEX_LIC = 00 +CODEC_INDEX_RIC = 01h +CODEC_INDEX_LX1C = 02h +CODEC_INDEX_RX1C = 03h +CODEC_INDEX_LX2C = 04h +CODEC_INDEX_RX2C = 05h +CODEC_INDEX_LDC = 06h +CODEC_INDEX_RDC = 07h +CODEC_INDEX_CDF = 08h +CODEC_INDEX_INTF = 09h +CODEC_INDEX_PIN = 0Ah +CODEC_INDEX_TEST = 0Bh +CODEC_INDEX_MISC = 0Ch +CODEC_INDEX_DIGMIX = 0Dh +CODEC_INDEX_UPR_COUNT = 0Eh +CODEC_INDEX_LWR_COUNT = 0Fh + +CODEC_MCE = 40h + +LDC_LDM = 80h +LDC_LDA = 3Fh + +RDC_RDM = 80h +RDC_RDA = 3Fh + +CDF_STEREO = 10h + +INTF_PEN = 01h +INTF_CEN = 02h +INTF_SDC = 04h +INTF_ACAL = 08h +INTF_PPIO = 40h +INTF_CPIO = 80h + +PIN_IEN = 2 + +TEST_ORL = 03h +TEST_ORR = 0Ch +TEST_DRS = 10h +TEST_ACI = 20h +TEST_PUR = 40h +TEST_COR = 80h + +;********************************** + +WSS16ScreenList Label + DW 16 + DW Near Ptr IdleFunctionList + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr WSSHeaderLine + + DW Near Ptr DriverText + + DW Near Ptr MixModeText + DW Near Ptr MixModeButton1 ; 6 + DW Near Ptr MixModeButton2 ; + DW Near Ptr MixModeButton3 ; 8 + DW Near Ptr MixModeButton4 ; 9 + + DW Near Ptr FilterText + DW Near Ptr FilterButton1 ; 11 + DW Near Ptr FilterButton2 + DW Near Ptr FilterButton3 + + DW Near Ptr VolumeText + DW Near Ptr VolumeBox1 + + DW Near Ptr MasterVolumeLeft ; 16 + DW Near Ptr MasterVolumeRight ; 17 + + DW Near Ptr SAM9407PortText + DW Near Ptr SAM9407ParametersText + DW Near Ptr SAM9407ParametersBox + + DW Near Ptr EqLBL ; 21 + DW Near Ptr EqLBR + DW Near Ptr EqLBF + + DW Near Ptr EqMLBL + DW Near Ptr EqMLBR + DW Near Ptr EqMLBF + + DW Near Ptr EqMHBL + DW Near Ptr EqMHBR + DW Near Ptr EqMHBF + + DW Near Ptr EqHBL + DW Near Ptr EqHBR + DW Near Ptr EqHBF + + DW Near Ptr EchoLevel + DW Near Ptr EchoTime + DW Near Ptr EchoFeedback + + DW Near Ptr SurroundVolume + DW Near Ptr SurroundDelay + + DW Near Ptr ReverbSend + DW Near Ptr ReverbVolume + DW Near Ptr ReverbType + DW Near Ptr ReverbTime + DW Near Ptr ReverbFeedback + + DW Near Ptr ChorusSend + DW Near Ptr ChorusVolume + DW Near Ptr ChorusType + DW Near Ptr ChorusDelay + DW Near Ptr ChorusFeedback + DW Near Ptr ChorusRate + DW Near Ptr ChorusDepth + + DW 0 + +WSSHeaderLine DW 10 + DB "Audiosystem EWS64 XL Codec Driver", 0 + +SAM9407ParametersText DW 1 + DB 36, 14 + DB 20h + DB "Low Band Left", 13 + DB "Low Band Right", 13 + DB "Low Band Frequency", 13 + DB "Med Low Band Left", 13 + DB "Med Low Band Right", 13 + DB "Med Low Band Frequency", 13 + DB "Med High Band Left", 13 + DB "Med High Band Right", 13 + DB "Med High Band Frequency", 13 + DB "High Band Left", 13 + DB "High Band Right", 13 + DB "High Band Frequency", 13 + DB "Echo Level", 13 + DB "Echo Time", 13 + DB "Echo Feedback", 13 + DB "Surround Volume", 13 + DB "Surround Delay", 13 + DB "Reverb Send", 13 + DB "Reverb Volume", 13 + DB "Reverb Type", 13 + DB "Reverb Time", 13 + DB "Reverb Feedback", 13 + DB "Chorus Send", 13 + DB "Chorus Volume", 13 + DB "Chorus Type", 13 + DB "Chorus Delay", 13 + DB "Chorus Feedback", 13 + DB "Chorus Rate", 13 + DB "Chorus Depth", 13 + DB 0 + +EqLBL DW 14 + DB 60, 14 + DW 0, 127 + DW 9, 2 + DW 13, 22, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqLBR DW 14 + DB 60, 15 + DW 0, 127 + DW 9, 3 + DW 21, 23, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqLBF DW 14 + DB 60, 16 + DW 0, 127 + DW 9, 4 + DW 22, 24, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqMLBL DW 14 + DB 60, 17 + DW 0, 127 + DW 9, 5 + DW 23, 25, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqMLBR DW 14 + DB 60, 18 + DW 0, 127 + DW 9, 6 + DW 24, 26, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqMLBF DW 14 + DB 60, 19 + DW 0, 127 + DW 9, 7 + DW 25, 27, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqMHBL DW 14 + DB 60, 20 + DW 0, 127 + DW 9, 8 + DW 26, 28, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqMHBR DW 14 + DB 60, 21 + DW 0, 127 + DW 9, 9 + DW 27, 29, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqMHBF DW 14 + DB 60, 22 + DW 0, 127 + DW 9, 10 + DW 28, 30, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqHBL DW 14 + DB 60, 23 + DW 0, 127 + DW 9, 11 + DW 29, 31, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqHBR DW 14 + DB 60, 24 + DW 0, 127 + DW 9, 12 + DW 30, 32, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqHBF DW 14 + DB 60, 25 + DW 0, 127 + DW 9, 13 + DW 31, 33, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EchoLevel DW 14 + DB 60, 26 + DW 0, 127 + DW 9, 15 + DW 32, 34, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EchoTime DW 14 + DB 60, 27 + DW 0, 127 + DW 9, 14 + DW 33, 35, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EchoFeedback DW 14 + DB 60, 28 + DW 0, 127 + DW 9, 16 + DW 34, 36, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +SurroundVolume DW 14 + DB 60, 29 + DW 0, 255 + DW 9, 17 + DW 35, 37, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +SurroundDelay DW 14 + DB 60, 30 + DW 0, 127 + DW 9, 18 + DW 36, 38, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ReverbSend DW 14 + DB 60, 31 + DW 0, 127 + DW 9, 19 + DW 37, 39, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ReverbVolume DW 14 + DB 60, 32 + DW 0, 255 + DW 9, 20 + DW 38, 40, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + + +ReverbType DW 14 + DB 60, 33 + DW 0, 7 + DW 9, 21 + DW 39, 41, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ReverbTime DW 14 + DB 60, 34 + DW 0, 127 + DW 9, 22 + DW 40, 42, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ReverbFeedback DW 14 + DB 60, 35 + DW 0, 127 + DW 9, 23 + DW 41, 43, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ChorusSend DW 14 + DB 60, 36 + DW 0, 127 + DW 9, 24 + DW 42, 44, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ChorusVolume DW 14 + DB 60, 37 + DW 0, 255 + DW 9, 25 + DW 43, 45, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ChorusType DW 14 + DB 60, 38 + DW 0, 7 + DW 9, 26 + DW 44, 46, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ChorusDelay DW 14 + DB 60, 39 + DW 0, 127 + DW 9, 27 + DW 45, 47, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ChorusFeedback DW 14 + DB 60, 40 + DW 0, 127 + DW 9, 28 + DW 46, 48, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ChorusRate DW 14 + DB 60, 41 + DW 0, 127 + DW 9, 29 + DW 47, 49, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ChorusDepth DW 14 + DB 60, 42 + DW 0, 127 + DW 9, 30 + DW 48, 0FFFFh, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +SAM9407ParametersBox DW 0 + DB 59, 13, 75, 43 + DB 25 + +EmptyObject DW 1 + DB 0, 0 + DB 0 + DB 0 + +SAM9407PortText DW 1 + DB 21, 47 + DB 21h + DB "Audiosystem EWS64 SAM9407 Port ", 0FDh, "Xh, Mixing Rate: ", 0FDh, "D", 0 +MixSpeed DW 48000 +SAM9407Port DW 0 + +DriverText DW 1 + DB 21, 48 + DB 21h + DB "Audiosystem EWS64 XL Codec Driver 1.2 for Impulse Tracker", 0 + +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +IdleFunctionList DD 0 + DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +VolumeText DW 1 + DB 2, 14 + DB 20h + DB "Master Volume Left", 13 + DB "Master Volume Right", 0 + +VolumeBox1 DW 0 + DB 21, 13, 31, 16 + DB 25 + +MasterVolumeLeft DW 9 + DB 22, 14 + DW 0, 63 + DW 9, 0 + DW 0FFFFh, 17, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +MasterVolumeRight DW 9 + DB 22, 15 + DW 0, 63 + DW 9, 1 + DW 16, 6, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +MixModeText DW 1 + DB 2, 18 + DB 20h + DB "Mixing Mode", 0 + +MixModeButton1 DW 2 + DW 17, 7, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment1 DW 0 + DW 0 + DW Offset SetMixMode +DriverSegment2 DW 0 + DB 3, 20, 32, 22, 8 + DB 0 + DB " 16 Bit, Non-Interpolated", 0 + +MixModeButton2 DW 2 + DW 6, 8, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment3 DW 0 + DW 2 + DW Offset SetMixMode +DriverSegment4 DW 0 + DB 3, 23, 32, 25, 8 + DB 0 + DB " 16 Bit, Interpolated", 0 + +MixModeButton3 DW 2 + DW 7, 9, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment5 DW 0 + DW 4 + DW Offset SetMixMode +DriverSegment6 DW 0 + DB 3, 26, 32, 28, 8 + DB 0 + DB " 32 Bit, Non-Interpolated", 0 + +MixModeButton4 DW 2 + DW 8, 11, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment7 DW 0 + DW 6 + DW Offset SetMixMode +DriverSegment8 DW 0 + DB 3, 29, 32, 31, 8 + DB 0 + DB " 32 Bit, Interpolated", 0 + +FilterText DW 1 + DB 2, 33 + DB 20h + DB "Filter mode", 0 + +FilterButton1 DW 2 + DW 9, 12, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment9 DW 0 + DW 0 + DW Offset SetFilter +DriverSegment10 DW 0 + DB 3, 35, 29, 37, 8 + DB 0 + DB " No Filter", 0 + +FilterButton2 DW 2 + DW 11, 13, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment11 DW 0 + DW 1 + DW Offset SetFilter +DriverSegment12 DW 0 + DB 3, 38, 29, 40, 8 + DB 0 + DB " 50% Filter", 0 + +FilterButton3 DW 2 + DW 12, 21, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment13 DW 0 + DW 2 + DW Offset SetFilter +DriverSegment14 DW 0 + DB 3, 41, 29, 43, 8 + DB 0 + DB " 75% Filter", 0 + + +; ÄÄ MixingRoutines ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + + +include dmasirq.inc +include mix.inc +include m12bit.mix +include m12biti.mix +include m32bit.mix +include m32biti.mix + +MixFunctionTables Label + +include m12bit.inc ; contains the tables +include m12biti.inc +include m32bit.inc +include m32biti.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +RelocationTable Label Word + DW Offset DriverSegment1, Offset DriverSegment2 + DW Offset DriverSegment3, Offset DriverSegment4 + DW Offset DriverSegment5, Offset DriverSegment6 + DW Offset DriverSegment7, Offset DriverSegment8 + DW Offset DriverSegment9, Offset DriverSegment10 + DW Offset DriverSegment11, Offset DriverSegment12 + DW Offset DriverSegment13, Offset DriverSegment14 + DW 0 + +; ÄÄ SAM9407InByte ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SAM9407InByte ; Returns AL + + Push DX + Mov DX, CS:SAM9407Port + Inc DX + +SAM9407InByte1: + In AL, DX + Test AL, AL + JS SAM9407InByte1 + + Dec DX + In AL, DX + Pop DX + + Ret + +EndP SAM9407InByte + +Comment ~ + +; ÄÄ ST97InWord ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SAM9407InWord ; Returns AX + + ClI + + Call SAM9407InByte + Mov AL, AH + + Call SAM9407InByte + XChg AL, AH + + StI + + Ret + +EndP SAM9407InWord + +; ÄÄ SAM9407InDWord ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SAM9407InDWord ; Returns EAX + + ClI + + Call SAM9407InByte + RoR EAX, 8 + + Call SAM9407InByte + RoR EAX, 8 + + Call SAM9407InByte + RoR EAX, 8 + + Call SAM9407InByte + RoR EAX, 8 + + StI + Ret + +EndP SAM9407InDWord + +~ + +; ÄÄ ST97SendByte ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SAM9407SendByte ; DX = port, AL = data + + Push AX + Push DX + Mov DX, CS:SAM9407Port + Inc DX + +SAM9407SendByte1: + In AL, DX + Test AL, 40h + JNZ SAM9407SendByte1 + + Pop DX + Pop AX + + Out DX, AL + + Ret + +EndP SAM9407SendByte + +Comment ~ + +; ÄÄ ST97OutByte ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SAM9407OutByte ; AL = data, AH = command, destroys AX + + ClI + Push DX + + Mov DX, CS:SAM9407Port + Inc DX + + XChg AH, AL + Call SAM9407SendByte + + Dec DX + + Mov AL, AH + Call SAM9407SendByte + + Pop DX + StI + + Ret + +EndP SAM9407OutByte + +; ÄÄ ST97OutWord ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SAM9407OutWord ; AX = data, BL = command, destroys AX + + ClI + Push DX + Push AX + + Mov DX, CS:SAM9407Port + Mov AL, BL + Inc DX + Call SAM9407SendByte + + Pop AX + Dec DX + Call SAM9407SendByte + + Mov AL, AH + Call SAM9407SendByte + + Pop DX + StI + + Ret + +EndP SAM9407OutWord + +; ÄÄ ST97OutDWord ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SAM9407OutDWord ; EAX = data, BL = command + + ClI + Push DX + Push AX + + Mov DX, CS:SAM9407Port + Mov AL, BL + Inc DX + Call SAM9407SendByte + + Pop AX + Dec DX + Call SAM9407SendByte + + ShR EAX, 8 + Call SAM9407SendByte + + ShR EAX, 8 + Call SAM9407SendByte + + ShR EAX, 8 + Call SAM9407SendByte + + Pop DX + StI + + Ret + +EndP SAM9407OutDWord + +~ + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetSAM9407 ; DI = index. 1 = full reinit. + + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + LEA SI, [SAM9407Strings+EDI+EDI-2] + Mov SI, [SI] + + LodsW + Mov CX, AX + +SetSAM9407_1: +; AH = 0 = normal data, 1 = command, 2 = param, 3 = ack. + + Mov DX, SAM9407Port + LodsW + + Cmp AH, 2 + JB SetSAM9407_3 + JA SetSAM9407_4 + + Mov AL, [VolumeTable+DI] + Jmp SetSAM9407_2 + +SetSAM9407_4: + Push CX + + Mov CX, 1024 + +SetSAM9407_6: + Call SAM9407InByte + Test AL, AL + LoopNZ SetSAM9407_6 + + Pop CX + + Jmp SetSAM9407_5 + +SetSAM9407_3: + And AH, 1 + Add DL, AH + +SetSAM9407_2: + Call SAM9407SendByte + +SetSAM9407_5: + Dec CX + JNZ SetSAM9407_1 + + Pop DS + PopA + + Ret + +EndP SetSAM9407 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixMode Far + + Push CS + Pop ES + Mov DI, Offset MixMode + + Ret + +EndP GetMixMode + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetFilter Far + + Push CS + Pop ES + Mov DI, Offset Filter + + Ret + +EndP GetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetFilter Far + + Mov AX, [SI+22] + Mov CS:FilterValue, 0 + Mov CS:Filter, AX + + Mov AX, 1 + Ret + +EndP SetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WaitCoDec + + Push CX + + Mov CX, 0F000h + +WaitCoDec1: + In AL, DX + Test AL, AL + JNS WaitCoDec2 + Loop WaitCoDec1 + + StC + +WaitCoDec2: + Pop CX + Ret + +EndP WaitCoDec + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WaitAutoCalibration + + Push CX + Mov CX, 0F000h + +WaitAutoCalibration1: + Mov AL, CODEC_INDEX_TEST + Out DX, AL + Inc DX + In AL, DX + Dec DX + Test AL, TEST_ACI + JNZ WaitAutoCalibration2 + Loop WaitAutoCalibration1 + + StC + +WaitAutoCalibration2: + Pop CX + Ret + +EndP WaitAutoCalibration + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixMode Far + + Mov AX, [SI+22] + + ClI + + Mov CS:MixMode, AX + + Mov BX, 180 + Mul BX + Mov CS:MixModeOffset, AX + + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS:RecalculateAllVolumes + + StI + + Mov AX, 1 + Ret + +EndP SetMixMode + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetWSSMixConst ; Work out value.. and nearest + ; mixspeed value. + + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, CmdLineMixSpeed + Mov CX, MixSpeed + Test AX, AX + JZ GetWSSMixConst1 + + Mov CX, 48000 + Cmp AX, CX + JA GetWSSMixConst1 + + Mov CX, 8000 + Cmp AX, CX + JB GetWSSMixConst1 + + Mov CX, AX + +GetWSSMixConst1: ; CX = desired mixspeed + Mov SI, Offset MixSpeedTable + Mov DX, 14 ; 14 different available speeds + + Xor BX, BX + +GetWSSMixConst2: + LodsW + Cmp AX, BX + JB GetWSSMixConst3 + Cmp AX, CX + JA GetWSSMixConst3 + + Mov BX, AX + Mov DH, [SI] + +GetWSSMixConst3: + LodsW ; Add SI, 2 + Dec DL + JNZ GetWSSMixConst2 + + Mov MixSpeed, BX + Mov WSSMixConst, DH + + Pop DS + PopA + Ret + +EndP GetWSSMixConst + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PingWSS ; Check BasePort, DX = BasePort + ; Preserves DX, destroys AX + + Push DX + + Inc DX + Inc DX + + In AL, DX + Xor AL, AL + Out DX, AL + + Dec DX + Dec DX + Call WaitCodec + JC PingWSSFailure + + In AL, DX + Test AL, AL + JS PingWSSFailure + + Mov AL, CODEC_INDEX_MISC + Out DX, AL + Inc DX ; DX = Data port + In AL, DX + Mov AH, AL ; AH = Revision + + Xor AL, AL ; Write 0 revision + Out DX, AL + In AL, DX + And AX, 8F8Fh + Cmp AL, AH + JNE PingWSSFailure + Dec DX ; DX = AD1848 baseport + + Mov AL, CODEC_MCE or CODEC_INDEX_INTF + Out DX, AL + Inc DX + Mov AL, INTF_ACAL or INTF_SDC + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_INTF + Out DX, AL + Inc DX + Mov AL, INTF_ACAL or INTF_SDC + Out DX, AL + Dec DX + + Call WaitAutoCalibration ; Returns carry if error + ; Carry clear if none. + +; JC PingWSSFailure + + Pop DX + Ret + +PingWSSFailure: + Pop DX + + StC + Ret + + +EndP PingWSS + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +PnP_SerialID DD 0 +PnP_VendorID DD 0 +PnP_ReadPort DW 0 +PnP_CSN DB 0 +PnP_CardFound DB 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_Delay + Assume DS:Driver + + Push AX CX + + Mov CX, 180h +PnP_Delay1: + In AL, 21h + Loop PnP_Delay1 + + Pop CX AX + Ret + +EndP PnP_Delay + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_WriteData + + Mov DX, 279h + Out DX, AL + + Mov AL, AH + Mov DH, 0Ah + Out DX, AL + Ret + +EndP PnP_WriteData + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_ReadData + + Mov DX, 279h + Out DX, AL + + Mov DX, PnP_ReadPort + In AL, DX + + Ret + +EndP PnP_ReadData + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_Isolate + + Mov AX, 402h + Call Pnp_WriteData ; Reset CSNs + +PnP_IsolateNextCard: + Mov AX, 0003h + Call PnP_WriteData ; Wake[0] + + Mov AX, PnP_ReadPort + ShL AX, 6 + Xor AL, AL + Call PnP_WriteData ; Set Read Data port. + + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + + Mov AL, 1 ; Serial Isolation + Mov DX, 279h + Out DX, AL + + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + + Mov BL, 6Ah + Mov CX, 64 + Mov DX, PnP_ReadPort + + ClI + +PnP_Isolate1: + ShR PnP_SerialID, 1 + RCR PnP_VendorID, 1 + + Mov BH, BL + ShR BH, 1 + Xor BH, BL + ShR BX, 1 + + In AL, DX + Mov AH, AL + Call PnP_Delay + In AL, DX + Call PnP_Delay + + Cmp AX, 55AAh + JNE PnP_Isolate2 + + Xor BL, 80h + Or PnP_SerialID, 80000000h + +PnP_Isolate2: + Dec CX + JNZ PnP_Isolate1 + + Mov CX, 8 + Xor BH, BH + +PnP_Isolate3: + ShR BH, 1 + + In AL, DX + Mov AH, AL + Call PnP_Delay + In AL, DX + Call PnP_Delay + Cmp AX, 55AAh + JNE PnP_Isolate4 + + Or BH, 80h + +PnP_Isolate4: + Dec CX + JNZ PnP_Isolate3 + + StI + + Cmp BL, BH ; Matching Checksum? + JNE PnP_IsolateFinished + + ; assign CSN + Inc PnP_CSN + + Mov AL, 6 + MOv AH, PnP_CSN + Call PnP_WriteData + + Cmp PnP_VendorID, PNPVENDORID + JNE PnP_IsolateNextCard +; Cmp PnP_SerialID, PNPSERIALID +; JNE PnP_IsolateNextCard + + Mov AL, 3 + Call PnP_WriteData + + Mov AX, 07h ; Configuration device + Call PnP_WriteData + + Mov AL, 60h + Call PnP_ReadData + Mov AH, AL + Mov AL, 61h + Call PnP_ReadData ; AX = address. + + Test AX, AX + JZ PnP_IsolateNextCard + + Cmp BasePort, 0FFFFh + JE PnPBasePortOK + + Cmp BasePort, AX + JNE PnP_IsolateNextCard + +PnPBasePortOK: + Mov BasePort, AX + + Mov AL, 70h + Call PnP_ReadData ; AL[3:0] = IRQ + And AX, 15 + JZ PnP_IsolateNextCard + Mov IRQ, AX + + Mov AL, 74h + Call PnP_ReadData ; AL[2:0] = DMA + And AX, 7 + Cmp AL, 4 + JE PnP_IsolateNextCard + Mov DMA, AX + + Mov AX, 407h ; Configuration device + Call PnP_WriteData + + Mov AL, 60h + Call PnP_ReadData + Mov AH, AL + Mov AL, 61h + Call PnP_ReadData ; AX = address. + Test AX, AX + JZ PnP_IsolateNextCard + + Mov SAM9407Port, AX + + Mov Pnp_CardFound, 1 + Jmp PnP_IsolateNextCard + +PnP_IsolateFinished: + Mov AL, PnP_CSN + ShL AL, 1 + Or AL, PnP_CardFound + + Ret + +EndP PnP_Isolate + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far ; returns carry clear if succesful + + Trace "Detecting EWS64XL" + + Push CS + Pop DS + + Xor AL, AL + Mov DX, 279h + Out DX, AL + Out DX, AL + + Mov AL, 6Ah ; Starting value + Mov CX, 32 + +PnP_InitiationKeyLoop: + Out DX, AL + + Mov AH, AL + ShR AH, 1 + Xor AH, AL + ShR AX, 1 + + Dec CX + JNZ PnP_InitiationKeyLoop + +; Try three ports before concluding no PnP cards: 20Fh, 27Bh, 213h + +PnP_DetectCardPort1: + Mov PnP_ReadPort, 20Fh + Call PnP_Isolate + JZ PnP_DetectCardPort2 + Test AL, 1 + JZ PnP_DetectCardNotFound + Jmp PnP_DetectCardFound + +PnP_DetectCardPort2: + Mov PnP_ReadPort, 27Bh + Call PnP_Isolate + JZ PnP_DetectCardPort3 + Test AL, 1 + JZ PnP_DetectCardNotFound + Jmp PnP_DetectCardFound + +PnP_DetectCardPort3: + Mov PnP_ReadPort, 213h + Call PnP_Isolate + Test AL, 1 + JNZ PnP_DetectCardFound + +PnP_DetectCardNotFound: + Trace "EWS64XL Not Found" + + StC + Jmp PnP_DetectEnd + +PnP_DetectCardFound: + Trace "EWS64XL Found" + ClC + +PnP_DetectEnd: ; Return PnP to wait for key state + Mov AX, 202h + Call PnP_WriteData + Mov EAX, 'Jeff' + + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixModeTable Label Word + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + +Proc MixSamples ; Given DS:SI = info tables, CX = numchannels + + ; 1. Clean buffer + ; + update variables + ; 2. Update parameters + ; 3. Mix func + ; 4. Return + + Push CX + + Mov CX, BytesToMix + Mov ES, MixSegment + Mov DI, MIXTABLESIZE + Xor EAX, EAX + Mov DX, CX + Add CX, CX + + Mov MixTransferOffset, DI ; } Memory write + + Cmp Stereo, 0 + JE MixSamples1 + + Mov DX, CX + +MixSamples1: + Rep StosD ; } Memory write + Mov MixTransferRemaining, DX ; } + + Pop CX + +MixSamples2: + Test Byte Ptr [SI], 1 + JZ MixSamplesEnd2 + Cmp Byte Ptr [SI+36h], 100 + JE MixSamplesEnd2 + + Push CX + Mov CX, [SI] + + Test CH, 2 + JZ MixSamples3 + And Byte Ptr [SI], Not 1 + + Jmp MixSamplesEnd +; Cmp MixMode, 8 ; Is it volume ramping? +; JB MixSamplesEnd + +MixSamples3: + Test CL, 20h ; New freq? + JZ MixSamples5 + + Mov AX, [SI+10h] + Mov DX, [SI+12h] + Mov BX, MixSpeed + Cmp DX, BX + JAE MixSamplesHandleError + + Div BX + ShL EAX, 16 + Xor AX, AX + Div BX + Mov STEPVALUE, EAX + +MixSamples4: + Test CH, 1 + JZ MixSamples5 + + Mov DWord Ptr [SI+1Ch], 0 ; Current Volume = 0 + ; for volume sliding. +MixSamples5: + Test CX, 8440h ; New volume or panning? + JZ MixSamplesMix + + Xor AX, AX + Test CH, 8 ; Muted? + JNZ MixModeCommon + + Mov BX, MixMode + Add BL, Stereo + Add BX, BX + Jmp [CS:MixModeTable+BX] + +Mix0Mode: ; 16-bit mixing, no interpolation +Mix0ModeMono: ; and 16-bit mixing, interpolation + Mov AL, [SI+20h] + ShR AL, 1 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 30 ; Use left only-mixing for mono + Jmp MixModeCommon + +Mix0ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix0ModeSurround + + Mul Byte Ptr [SI+20h] ; Final volume + Add AX, 64 + ShR AX, 7 + Mov [SI+0Ch], AX ; Store into right volume + + Mov AL, 64 + Sub AL, [SI+37h] + Mul Byte Ptr [SI+20h] + Add AX, 64 + ShR AX, 7 + Mov [SI+0Eh], AX ; Left volume + + Mov CH, AL ; CH = left volume + Mov CL, [SI+0Ch] ; CL = right volume + Mov AX, 0 + + Test CX, CX + JZ MixModeCommon + + Mov AL, 30 ; Left only... + Test CL, CL + JZ MixModeCommon + + Mov AL, 60 + Test CH, CH + JZ MixModeCommon + + Mov AL, 90 + Cmp CL, CH + JZ MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix0ModeSurround: + Mov AL, [SI+20h] + ShR AL, 2 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 150 ; Surround + Jmp MixModeCommon + +Mix6ModeMono: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 8 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Test AX, AX + JZ MixModeCommon + Mov AX, 30 + Jmp MixModeCommon + +Mix6ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix6ModeSurround + + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Ch], AX ; Store into right volume + Mov BX, AX + ShL EAX, 16 + + Mov AL, 64 ; Do left volume + Sub AL, [SI+37h] ; AL = 64-FinalPan + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Eh], AX + + Mov ECX, EAX + + ; BX = right volume + ; CX = Left volume + Mov AX, 0 + Test ECX, ECX + JZ MixModeCommon + + Mov AL, 30 + Test BX, BX + JZ MixModeCommon + + Mov AL, 60 + Test CX, CX + JZ MixModeCommon + + Mov AL, 90 + Cmp CX, BX + JE MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix6ModeSurround: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 9 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + JZ MixModeCommon + Mov AX, 150 + Jmp MixModeCommon + +MixModeCommon: ; Requires AX = 30/60/90 etc. depending + ; On mixing mode type. + ; This will add 180 for 16-bit, + ; And sort out loop types. + Mov BL, [SI+0Ah] + Test Byte Ptr [SI+18h], 2 ; 16 bit? + JZ MixModeCommon1 + + Add AX, 180 + +MixModeCommon1: + Cmp BL, 8 + JB MixModeCommon3 ; No loop + JE MixModeCommon2 ; Forwards loop + + Add AX, 10 + +MixModeCommon2: + Add AX, 10 + +MixModeCommon3: + Add AX, Offset MixFunctionTables + Add AX, MixModeOffset + Mov [SI+8], AX ; Offset... + +MixSamplesMix: + Mov BX, [SI+8] ; BX = offset into + Mov EAX, [CS:BX+2] + Mov DWord Ptr PreMixFunction, EAX + Mov EAX, [CS:BX+6] + Mov DWord Ptr MixFunctionSeparateBackwards, EAX + + Mov AX, BytesToMix + Mov MixBlockSize, AX + Mov MixBufferOffset, MIXTABLESIZE + + Mov EAX, CURRENTPOSITION + Mov OLDPOSITION, EAX + + Call Word Ptr [CS:BX] + + And Word Ptr [SI], 0111100010001101b + Jmp MixSamplesEnd + +MixSamplesHandleError: + Mov Word Ptr [SI], 200h + + Test Byte Ptr [SI+3Ah], 80h + JNZ MixSamplesEnd + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Turn off channel + +MixSamplesEnd: + Pop CX + +MixSamplesEnd2: + Add SI, 128 + Dec CX + JNZ MixSamples2 + + Ret + +EndP MixSamples + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WSSIRQHandler + + PushAD + Push DS + Push ES + + ClD + + Mov AX, CS + Mov DS, AX + Assume DS:Driver + + Mov DX, [BasePort] + Add DX, 2 + In AL, DX + Test AL, 1 + JZ WSSAckIRQ2 + + Xor AL, AL + Out DX, AL + +WSSAckIRQ2: + Mov AL, 20h + Cmp IRQ, 8 + JB WSSAckIRQ1 + + Out 0A0h, AL + +WSSAckIRQ1: + Out 20h, AL + +DMAPort1 EQU $+1 + In AL, 1 + Mov BL, AL +DMAPort2 EQU $+1 + In AL, 1 + Mov BH, AL + + Xor AX, AX + + Cmp BX, DMABUFFERLENGTH/2 + JB WSSIRQHandler1 + + Mov AX, DMABUFFERLENGTH/2 + +WSSIRQHandler1: + CLD + ; OK... time to get next block + ; Check whether stereo thing is on.. + ; + LES DI, [ActualDMAPtr] + Add DI, AX + + Mov BX, DMASize ; BX = bytes required + ShR BX, 1 + ; BX = samples required + Mov BP, 8 ; Skip for mono + Mov CL, 14 ; Shift for mono + + Cmp Stereo, 0 + JE WSSIRQHandlerMono + + Mov BP, 4 ; Stereo skip value. + Dec CL + +WSSIRQHandlerMono: + Call SaveEMSPageFrame + + Cmp MixTransferRemaining, 0 + JNE WSSIRQHandler4 + Assume DS:Nothing + +WSSIRQHandler3: + Push BX + Push CX + Push BP + Push ES + Push DI + + Call Update + Call MixSamples + + Pop DI + Pop ES + Pop BP + Pop CX + Pop BX + +WSSIRQHandler4: + Mov DS, MixSegment + Mov SI, MixTransferOffset + Mov DX, BX ; DX = samples to transfer + Cmp DX, MixTransferRemaining + JBE WSSIRQHandler5 + + Mov DX, MixTransferRemaining + +WSSIRQHandler5: + Push DX + Cmp CS:Filter, 1 + JB WSSIRQHandler6 + JE WSSIRQHFilter + + Cmp CS:Stereo, 0 + JE WSSIRQ3QFilterMono + +WSSIRQ3QFilterStereo: + Push BX + + Mov EBX, FilterValue + Mov EBP, FilterValue2 + ShR DX, 1 + +WSSIRQ3QFilterStereo1: + Mov EAX, EBX + Mov ECX, EBP + Add EAX, [SI] + Add ECX, [SI+4] + SAR EAX, 1 + SAR ECX, 1 + Add EBX, EAX + Add EBP, ECX + SAR EBX, 1 + SAR EBP, 1 + + Mov EAX, EBX + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSS3QFilterStereoClip1 + Cmp EAX, 7FFFh + JG WSS3QFilterStereoClip2 + +WSSIRQ3QFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSS3QFilterStereoClip3 + Cmp EAX, 7FFFh + JG WSS3QFilterStereoClip4 + +WSSIRQ3QFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ WSSIRQ3QFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp WSSMixTransferEnd + +WSSIRQ3QFilterMono: + Push BX + + Mov EBX, FilterValue + +WSSIRQ3QFilterMono1: + Mov EAX, EBX + Add EAX, [SI] + SAR EAX, 1 + Add EBX, EAX + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL WSS3QFilterMonoClip1 + Cmp EAX, 7FFFh + JG WSS3QFilterMonoClip2 + +WSSIRQ3QFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ WSSIRQ3QFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp WSSMixTransferEnd + +WSSIRQHFilter: + Cmp CS:Stereo, 0 + JE WSSIRQHFilterMono + +WSSIRQHFilterStereo: + Push BX + + Mov EBX, FilterValue + Mov EBP, FilterValue2 + ShR DX, 1 + +WSSIRQHFilterStereo1: + Add EBX, [SI] + Add EBP, [SI+4] + + SAR EBX, 1 + SAR EBP, 1 + + Mov EAX, EBX + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSSHFilterStereoClip1 + Cmp EAX, 7FFFh + JG WSSHFilterStereoClip2 + +WSSIRQHFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSSHFilterStereoClip3 + Cmp EAX, 7FFFh + JG WSSHFilterStereoClip4 + +WSSIRQHFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ WSSIRQHFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp WSSMixTransferEnd + +WSSIRQHFilterMono: + Push BX + + Mov EBX, FilterValue + +WSSIRQHFilterMono1: + Add EBX, [SI] + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL WSSHFilterMonoClip1 + Cmp EAX, 7FFFh + JG WSSHFilterMonoClip2 + +WSSIRQHFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ WSSIRQHFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp WSSMixTransferEnd + +WSSIRQHandler6: + Mov EAX, [SI] + SAR EAX, CL + + Cmp EAX, -8000h + JL WSSIRQHandlerClip1 + Cmp EAX, 7FFFh + JG WSSIRQHandlerClip2 + +WSSIRQHandler7: + StosW ; } Memory write + + Add SI, BP + Dec DX + JNZ WSSIRQHandler6 + +WSSMixTransferEnd: + Pop DX + + Sub MixTransferRemaining, DX ; } Memory write + Sub BX, DX + JNZ WSSIRQHandler3 + + Mov MixTransferOffset, SI ; } Memory write + + Call RestoreEMSPageFrame + + Pop ES + Pop DS + PopAD + IRet + +WSSIRQHandlerClip1: + Mov AX, 8000h + Jmp WSSIRQHandler7 + +WSSIRQHandlerClip2: + Mov AX, 7FFFh + Jmp WSSIRQHandler7 + +WSSHFilterMonoClip1: + Mov AX, 8000h + Jmp WSSIRQHFilterMono2 + +WSSHFilterMonoClip2: + Mov AX, 7FFFh + Jmp WSSIRQHFilterMono2 + +WSSHFilterStereoClip1: + Mov AX, 8000h + Jmp WSSIRQHFilterStereo2 + +WSSHFilterStereoClip2: + Mov AX, 7FFFh + Jmp WSSIRQHFilterStereo2 + +WSSHFilterStereoClip3: + Mov AX, 8000h + Jmp WSSIRQHFilterStereo3 + +WSSHFilterStereoClip4: + Mov AX, 7FFFh + Jmp WSSIRQHFilterStereo3 + +WSS3QFilterMonoClip1: + Mov AX, 8000h + Jmp WSSIRQ3QFilterMono2 + +WSS3QFilterMonoClip2: + Mov AX, 7FFFh + Jmp WSSIRQ3QFilterMono2 + +WSS3QFilterStereoClip1: + Mov AX, 8000h + Jmp WSSIRQ3QFilterStereo2 + +WSS3QFilterStereoClip2: + Mov AX, 7FFFh + Jmp WSSIRQ3QFilterStereo2 + +WSS3QFilterStereoClip3: + Mov AX, 8000h + Jmp WSSIRQ3QFilterStereo3 + +WSS3QFilterStereoClip4: + Mov AX, 7FFFh + Jmp WSSIRQ3QFilterStereo3 + +EndP WSSIRQHandler + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Add DI, Offset IRQData + Mov BX, [CS:DI] + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset WSSIRQHandler + + XChg [ES:BX], EAX + Mov OldWSSIRQHandler, EAX + + Mov AX, IMR + And AX, [DI+2] + + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Pop ES + PopAD + + Ret + +EndP SetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Mov BX, [IRQData+DI] + + Mov EAX, OldWSSIRQHandler + Mov [ES:BX], EAX + + Pop ES + PopAD + + Ret + +EndP ResetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StopWSS + + Mov DX, BasePort + + Mov AL, CODEC_INDEX_INTF + Out DX, AL + Inc DX + In AL, DX + And AL, Not INTF_PEN + Out DX, AL + + Inc DX + In AL, DX + Xor AL, AL + Out DX, AL + + Dec DX + Dec DX + + Mov AL, CODEC_INDEX_PIN + Out DX, AL + Inc DX + Xor AL, AL + Out DX, AL + + Ret + +EndP StopWSS + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StartWSS + + PushA + Push ES + Push DS + + Push CS + Pop DS + Assume DS:Driver + + ; Setup DMA + Mov BX, DMASegment + Xor AX, AX + Mov DX, DMA + Mov DI, DMABUFFERLENGTH + Call SetDMA + + LES DI, ActualDMAPtr + Xor AX, AX + Mov CX, DMABUFFERLENGTH/2 + Rep StosW + + Mov MixTransferRemaining, 0 + + Mov DX, BasePort + Call PingWSS + + Mov AL, CODEC_INDEX_PIN + Out DX, AL + Inc DX + Mov AL, PIN_IEN + Out DX, AL + Dec DX + + Mov AH, WSSMixConst ; Set format/frequency + Cmp Stereo, 0 + JE StartWSS1 + + Or AH, CDF_STEREO + +StartWSS1: + Mov AL, CODEC_MCE or CODEC_INDEX_CDF + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Call WaitCodec + + Mov AL, CODEC_INDEX_CDF + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Call WaitAutoCalibration + + ; Start playback + Mov AL, CODEC_INDEX_LWR_COUNT + Out DX, AL + Inc DX + + Mov AX, DMASize + ShR AX, 1 + + Cmp Stereo, 0 + JE StartWSS2 + + ShR AX, 1 + +StartWSS2: + Dec AX + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_UPR_COUNT + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_INTF + Out DX, AL + Inc DX + In AL, DX + Or AL, INTF_PEN + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_LDC + Out DX, AL + Inc DX + In AL, DX + And AL, Not LDC_LDM + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_RDC + Out DX, AL + Inc DX + In AL, DX + And AL, Not RDC_RDM + Out DX, AL + Dec DX + + Pop DS + Pop ES + PopA + + Ret + +EndP StartWSS + Assume DS:Nothing + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Trace "EWS64XL InitSound" + + Push CS + Pop DS + Assume DS:Driver + + Mov SI, Offset RelocationTable + +RelocationFix: + LodsW + Test AX, AX + JZ RelocationEnd + Mov BX, AX + Mov [BX], DS + Jmp RelocationFix + + +RelocationEnd: + Call GetEMSPageFrame + Mov EMSPageFrame, AX + + In AL, 0A1h + Mov AH, AL + In AL, 21h + Mov IMR, AX + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + Call GetWSSMixConst + + Mov AX, 2643 + Mul MixSpeed + Add AX, 0FFFFh + AdC DX, 2080 + + Mov BX, (DMABUFFERLENGTH*2)/16 + Add BX, DX + + ; Allocate MixSegment first + Mov AH, 48h + + Int 21h + JNC InitSound1 + +InitSoundNoMemory: + Mov SI, Offset WSSNoMemoryMsg + Ret + +InitSound1: + Mov MixSegment, AX + Add AX, DX + Mov DMASegment, AX + + Trace "EWS64XL Memory Allocated" + + + Call SetIRQ + Call GetTempo + Call SetTempo + + Trace "EWS64XL IRQ Hooked" + + Mov DX, BasePort + Mov AL, CODEC_INDEX_RDC + Out DX, AL + Inc DX + In AL, DX + Mov AH, AL + Dec DX + + Mov AL, CODEC_INDEX_LDC + Out DX, AL + Inc DX + In AL, DX + And AX, 3F3Fh + Neg AL + Neg AH + Add AL, 3Fh + Add AH, 3Fh + Mov [Word Ptr VolumeTable], AX + + Trace "EWS64XL Volume Settings Received" + + Mov DI, 1 + Call SetSAM9407 + + Trace "EWS64XL SAM9407 InitString finished" + + Mov SI, Offset WSSMsg + + Mov AX, BasePort + Mov BX, IRQ + Mov CX, DMA + + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Call StopWSS + Call ResetIRQ + Call SetIRQ + + Mov SI, Offset ReInitMsg + Mov BX, 40 + Call SetInfoLine + + Mov AL, Stereo + Call SetStereo + + Pop ES + Pop DS + PopA + + Ret + +EndP ReInitSound + Assume DS:Nothing + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, IMR + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Mov AX, MixSegment + Test AX, AX + JZ UnInitSound1 + + Mov ES, AX + Mov AH, 49h ; Release MixSegment + Int 21h + + Call StopWSS + Call ResetIRQ + +UnInitSound1: + Call GotoHomeDirectory + + ; Now to save config into driver file. + Mov AX, 3D02h ; Read write access + Mov DX, Offset DriverName + Int 21h + JC SetMixMode1 + + Mov BX, AX + + Mov AX, 4200h + Xor CX, CX + Mov DX, Offset CONFIGURATIONOFFSET + Int 21h + JC SetMixMode2 + + Mov AH, 40h + Mov CX, CONFIGSIZE + Mov DX, Offset MixMode + Int 21h + +SetMixMode2: + Mov AH, 3Eh + Int 21h + +SetMixMode1: + Ret + +EndP UnInitSound + Assume DS:Nothing + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + Ret + +EndP Poll + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Push AX + Push BX + Push DX + + Push BX + + Mov AX, MixSpeed + Mov BX, AX + Xor DX, DX + + ShL AX, 1 + RCL DX, 1 ; DX:AX = Mixspeed*2 + + ShR BX, 1 ; BX = Mixspeed/2 + + Add AX, BX + AdC DX, 0 ; DX:AX = Mixspeed*2.5 + + Pop BX ; BX = tempo + Div BX + + Mov BytesToMix, AX + + Pop DX + Pop BX + Pop AX + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + PushA + Push DS + + Mov BX, AX ; BX = MixVolume + Mov CS:MixVolume, BX + + Mov AX, CS:MixSegment + Test AX, AX + JZ SetMixVolume2 + + Mov DS, AX + + Mov CX, MIXTABLESIZE/2 + Mov SI, MIXTABLESIZE-2; Starting point - working backwards + +SetMixVolume1: + Mov AX, CX + + Dec AX ; AH = volume, AL = wave value. + Xor DX, DX + XChg AH, DL ; DL = Volume, AX = wave value + CBW + + IMul DX ; DX:AX = Volume * Wave Value + ; Ranges -8192->8128 + + IMul BX ; DX:AX = Volume * Wave Value * Mixing Volume + ; Ranges -1048576->1040384 + + Add AX, 64 + AdC DX, 0 + + ShRD AX, DX, 7 + Mov [SI], AX + Sub SI, 2 + + Loop SetMixVolume1 + +SetMixVolume2: + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS: RecalculateAllVolumes + + Pop DS + PopA + + Ret + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc RecalculateAllFrequencies + + Call GetChannelTables + +RecalculateAllFrequencies1: + Or Byte Ptr [SI], 32 + + Add SI, 128 + Dec CX + JNZ RecalculateAllFrequencies1 + + Ret + +EndP RecalculateAllFrequencies + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Mov CS:Stereo, AL + Cmp CS:MixSegment, 0 + JE SetStereo1 + + Push AX + + Call StopWSS + Call StartWSS + + Call RecalculateAllFrequencies + + Pop DI + + And DI, 1 + Add DI, 31 + Call SetSAM9407 + + Mov DI, 2 +SetStereo2: + Call SetSAM9407 + Inc DI + Cmp DI, 30 + JBE SetStereo2 + +SetStereo1: + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include loadsam.inc + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset WSS16ScreenList + + ClC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far + + Xor AH, AH + Mov AL, [CS:VolumeTable+DI] + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UpdateSoundcardVariables + + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov DX, BasePort + + Mov AL, CODEC_INDEX_LDC + Out DX, AL + Inc DX + Mov AX, 3F3Fh + Sub AX, [Word Ptr VolumeTable] + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_RDC + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + + Pop DS + PopA + + Ret + +EndP UpdateSoundcardVariables + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far + + Mov [CS:VolumeTable+DI], AL + Cmp DI, 2 + JB SetVariable1 + + Call SetSAM9407 + Ret + +SetVariable1: + Call UpdateSoundcardVariables + Ret + +EndP SetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. + +StopAfterPlay DW 0 +DefaultChannels DW 64 + DW 5 Dup (0) + + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/EWSCODMX.ASM b/SoundDrivers/EWSCODMX.ASM new file mode 100755 index 0000000..12da420 --- /dev/null +++ b/SoundDrivers/EWSCODMX.ASM @@ -0,0 +1,2531 @@ +; +; EWS 64 Codec Driver +; + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc +include mmx.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;********************************** + +TRACEENABLED = 0 +CREATENEWLOGFILE = 1 + +include debug.inc + +OUTPUTFILTERENABLED EQU 0 +STEREOENABLED EQU 1 +DMABUFFERLENGTH EQU 8192 +MIXRESOLUTION EQU 32 ; 32 bit mixing for +DATAFLAG EQU 200h +ACKFLAG EQU 300h + +PNPSERIALID EQU 98B03C20h +PNPVENDORID EQU 36A8630Eh + +DMASize DW 4096 + +WSSMsg DB "Audiosystem EWS64 XL Codec", 13 + DB "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, DMA ", 0FDh, "D", 0 + +WSSNoMemoryMsg DB "Audiosystem EWS64 XL Codec", 13 + DB "Error: Insufficient memory", 0 + +ReinitMsg DB "Audiosystem EWS64 XL reinitialised", 0 + +DriverName DB "ITEWSCOD.MMX", 0 + +ALIGN 2 + +Forced DB 0 +Stereo DB 0 +MixVolume DW 0 + +BytesToMix DW 1000 +WSSMixConst DB 0 + +MixSegment DW 0 + +MixTransferOffset DW 0 +MixTransferRemaining DW 0 + +CONFIGURATIONOFFSET EQU $+128 +CONFIGSIZE EQU 35 +MixMode DW 0 +MixModeOffset DW 0 +VolumeTable DB 56, 56 + DB 60h, 60h, 0Ch ; Low Band + DB 40h, 40h, 1Bh ; Med Low Band + DB 40h, 40h, 72h ; Med High Band + DB 60h, 60h, 40h ; High Band + DB 0, 0, 0 ; Echo + DB 0, 2 ; Surround + DB 0, 90h, 4, 7Fh, 22h ; Reverb + DB 0, 90h, 2, 40h, 9, 3, 13h ; Chorus + +IMR DW 0 +OldWSSIRQHandler DD 0 + +; String format, Count, [Data/Port]*Count +; Port = 1 for Control port, 0 for data port. + +SAM9407Reset DW 66 + DW 1BEh, 16Fh, 7Fh, 7Fh, ACKFLAG ; Audio in on + DW 1BEh, 168h, 7Fh, 7Fh, ACKFLAG ; Echo on + DW 1BEh, 16Ch, 7Fh, 7Fh, ACKFLAG ; Reverb on + DW 1BEh, 16Dh, 7Fh, 7Fh, ACKFLAG ; Chorus on + DW 1BEh, 16Bh, 0, 0, ACKFLAG ; Equalizer type + DW 1BEh, 16Eh, 7Fh, 7Fh, ACKFLAG ; Surround on + DW 1BEh, 165h, 7Fh, 7Fh ; Post eff on Audio in + DW 1BEh, 166h, 7Fh, 7Fh ; Post eff on reverb, chorus + DW 1BEh, 133h, 0, 0 ; 2 Speaker + DW 1BEh, 120h, 7Fh, 7Fh ; Stereo input 2 + DW 1BEh, 134h, 0FFh, 0FFh ; Left gain + DW 1BEh, 135h, 0FFh, 0FFh ; Right gain + DW 1BEh, 136h, 0, 0 ; Left pan + DW 1BEh, 137h, 7Fh, 7Fh ; Right pan + DW 1BEh, 107h, 0FFh, 0FFh ; Master volume + +SAM9407EqLBL DW 4 + DW 1BEh, 110h, DATAFLAG, 60h +SAM9407EqLBR DW 4 + DW 1BEh, 114h, DATAFLAG, 60h +SAM9407EqLBF DW 4 + DW 1BEh, 118h, DATAFLAG, 0Ch +SAM9407EqMLBL DW 4 + DW 1BEh, 111h, DATAFLAG, 40h +SAM9407EqMLBR DW 4 + DW 1BEh, 115h, DATAFLAG, 40h +SAM9407EqMLBF DW 4 + DW 1BEh, 119h, DATAFLAG, 1Bh +SAM9407EqMHBL DW 4 + DW 1BEh, 112h, DATAFLAG, 40h +SAM9407EqMHBR DW 4 + DW 1BEh, 116h, DATAFLAG, 40h +SAM9407EqMHBF DW 4 + DW 1BEh, 11Ah, DATAFLAG, 72h +SAM9407EqHBL DW 4 + DW 1BEh, 113h, DATAFLAG, 60h +SAM9407EqHBR DW 4 + DW 1BEh, 117h, DATAFLAG, 60h +SAM9407EqHBF DW 4 + DW 1BEh, 11Bh, DATAFLAG, 0Ch +SAM9407EchoLevel DW 4 + DW 1BEh, 128h, DATAFLAG, 0 +SAM9407EchoTime DW 4 + DW 1BEh, 129h, DATAFLAG, 2Bh +SAM9407EchoFeed DW 4 + DW 1BEh, 12Ah, DATAFLAG, 40h +SAM9407SurroundVolume DW 4 + DW 1BEh, 130h, DATAFLAG, 0 +SAM9407SurroundDelay DW 4 + DW 1BEh, 131h, DATAFLAG, 2 +SAM9407ReverbSend DW 4 + DW 1BEh, 127h, DATAFLAG, 0 +SAM9407ReverbVolume DW 3 + DW 1BEh, 13Ah, DATAFLAG +SAM9407ReverbType DW 4 + DW 1BEh, 169h, DATAFLAG, 4 +SAM9407ReverbTime DW 3 + DW 1BEh, 178h, DATAFLAG +SAM9407ReverbFeedback DW 3 + DW 1BEh, 179h, DATAFLAG +SAM9407ChorusSend DW 4 + DW 1BEh, 124h, DATAFLAG, 0 +SAM9407ChorusVolume DW 3 + DW 1BEh, 13Bh, DATAFLAG +SAM9407ChorusType DW 4 + DW 1BEh, 16Ah, DATAFLAG, 2 +SAM9407ChorusDelay DW 3 + DW 1BEh, 174h, DATAFLAG +SAM9407ChorusFeedback DW 3 + DW 1BEh, 175h, DATAFLAG +SAM9407ChorusRate DW 3 + DW 1BEh, 176h, DATAFLAG +SAM9407ChorusDepth DW 3 + DW 1BEh, 177h, DATAFLAG +SAM9407Mono DW 4 + DW 1BEh, 132h, 7Fh, 0 +SAM9407Stereo DW 4 + DW 1BEh, 132h, 0, 0 + +SAM9407Strings DW Offset SAM9407Reset ;1 + DW Offset SAM9407EqLBL, Offset SAM9407EqLBR + DW Offset SAM9407EqLBF + DW Offset SAM9407EqMLBL, Offset SAM9407EqMLBR + DW Offset SAM9407EqMLBF + DW Offset SAM9407EqMHBL, Offset SAM9407EqMHBR + DW Offset SAM9407EqMHBF + DW Offset SAM9407EqHBL, Offset SAM9407EqHBR + DW Offset SAM9407EqHBF + DW Offset SAM9407EchoLevel ; 14 + DW Offset SAM9407EchoTime + DW Offset SAM9407EchoFeed + DW Offset SAM9407SurroundVolume ; 17 + DW Offset SAM9407SurroundDelay + DW Offset SAM9407ReverbSend ; 19 + DW Offset SAM9407ReverbVolume + DW Offset SAM9407ReverbType + DW Offset SAM9407ReverbTime + DW Offset SAM9407ReverbFeedback ; 23 + DW Offset SAM9407ChorusSend ; 24 + DW Offset SAM9407ChorusVolume + DW Offset SAM9407ChorusType + DW Offset SAM9407ChorusDelay + DW Offset SAM9407ChorusFeedback + DW Offset SAM9407ChorusRate + DW Offset SAM9407ChorusDepth ; 30 + DW Offset SAM9407Mono ; 31 + DW Offset SAM9407Stereo + +MixSpeedTable DW 5513, 41h + DW 6615, 4Fh + DW 8000, 40h + DW 9600, 4Eh + DW 11025, 43h + DW 16000, 42h + DW 18900, 45h + DW 22050, 47h + DW 27429, 44h + DW 32000, 46h + DW 33075, 4Dh + DW 37800, 49h + DW 44100, 4Bh + DW 48000, 4Ch + +include irq.inc + +;********************************** +; WSS Registers +;********************************** + +CODEC_INDEX_LIC = 00 +CODEC_INDEX_RIC = 01h +CODEC_INDEX_LX1C = 02h +CODEC_INDEX_RX1C = 03h +CODEC_INDEX_LX2C = 04h +CODEC_INDEX_RX2C = 05h +CODEC_INDEX_LDC = 06h +CODEC_INDEX_RDC = 07h +CODEC_INDEX_CDF = 08h +CODEC_INDEX_INTF = 09h +CODEC_INDEX_PIN = 0Ah +CODEC_INDEX_TEST = 0Bh +CODEC_INDEX_MISC = 0Ch +CODEC_INDEX_DIGMIX = 0Dh +CODEC_INDEX_UPR_COUNT = 0Eh +CODEC_INDEX_LWR_COUNT = 0Fh + +CODEC_MCE = 40h + +LDC_LDM = 80h +LDC_LDA = 3Fh + +RDC_RDM = 80h +RDC_RDA = 3Fh + +CDF_STEREO = 10h + +INTF_PEN = 01h +INTF_CEN = 02h +INTF_SDC = 04h +INTF_ACAL = 08h +INTF_PPIO = 40h +INTF_CPIO = 80h + +PIN_IEN = 2 + +TEST_ORL = 03h +TEST_ORR = 0Ch +TEST_DRS = 10h +TEST_ACI = 20h +TEST_PUR = 40h +TEST_COR = 80h + +;********************************** + +WSS16ScreenList Label + DW 16 + DW Near Ptr IdleFunctionList + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr WSSHeaderLine + + DW Near Ptr DriverText + + DW Near Ptr MixModeText + DW Near Ptr MixModeButton1 ; 6 + DW Near Ptr MixModeButton2 ; + DW Near Ptr MixModeButton3 ; 8 + DW Near Ptr MixModeButton4 ; 9 + + DW Near Ptr EmptyObject + DW Near Ptr EmptyObject + DW Near Ptr EmptyObject + DW Near Ptr EmptyObject + + DW Near Ptr VolumeText + DW Near Ptr VolumeBox1 + + DW Near Ptr MasterVolumeLeft ; 16 + DW Near Ptr MasterVolumeRight ; 17 + + DW Near Ptr SAM9407PortText + DW Near Ptr SAM9407ParametersText + DW Near Ptr SAM9407ParametersBox + + DW Near Ptr EqLBL ; 21 + DW Near Ptr EqLBR + DW Near Ptr EqLBF + + DW Near Ptr EqMLBL + DW Near Ptr EqMLBR + DW Near Ptr EqMLBF + + DW Near Ptr EqMHBL + DW Near Ptr EqMHBR + DW Near Ptr EqMHBF + + DW Near Ptr EqHBL + DW Near Ptr EqHBR + DW Near Ptr EqHBF + + DW Near Ptr EchoLevel + DW Near Ptr EchoTime + DW Near Ptr EchoFeedback + + DW Near Ptr SurroundVolume + DW Near Ptr SurroundDelay + + DW Near Ptr ReverbSend + DW Near Ptr ReverbVolume + DW Near Ptr ReverbType + DW Near Ptr ReverbTime + DW Near Ptr ReverbFeedback + + DW Near Ptr ChorusSend + DW Near Ptr ChorusVolume + DW Near Ptr ChorusType + DW Near Ptr ChorusDelay + DW Near Ptr ChorusFeedback + DW Near Ptr ChorusRate + DW Near Ptr ChorusDepth + + DW 0 + +WSSHeaderLine DW 10 + DB "Audiosystem EWS64 XL Codec Driver", 0 + +SAM9407ParametersText DW 1 + DB 36, 14 + DB 20h + DB "Low Band Left", 13 + DB "Low Band Right", 13 + DB "Low Band Frequency", 13 + DB "Med Low Band Left", 13 + DB "Med Low Band Right", 13 + DB "Med Low Band Frequency", 13 + DB "Med High Band Left", 13 + DB "Med High Band Right", 13 + DB "Med High Band Frequency", 13 + DB "High Band Left", 13 + DB "High Band Right", 13 + DB "High Band Frequency", 13 + DB "Echo Level", 13 + DB "Echo Time", 13 + DB "Echo Feedback", 13 + DB "Surround Volume", 13 + DB "Surround Delay", 13 + DB "Reverb Send", 13 + DB "Reverb Volume", 13 + DB "Reverb Type", 13 + DB "Reverb Time", 13 + DB "Reverb Feedback", 13 + DB "Chorus Send", 13 + DB "Chorus Volume", 13 + DB "Chorus Type", 13 + DB "Chorus Delay", 13 + DB "Chorus Feedback", 13 + DB "Chorus Rate", 13 + DB "Chorus Depth", 13 + DB 0 + +EqLBL DW 14 + DB 60, 14 + DW 0, 127 + DW 9, 2 + DW 9, 22, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqLBR DW 14 + DB 60, 15 + DW 0, 127 + DW 9, 3 + DW 21, 23, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqLBF DW 14 + DB 60, 16 + DW 0, 127 + DW 9, 4 + DW 22, 24, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqMLBL DW 14 + DB 60, 17 + DW 0, 127 + DW 9, 5 + DW 23, 25, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqMLBR DW 14 + DB 60, 18 + DW 0, 127 + DW 9, 6 + DW 24, 26, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqMLBF DW 14 + DB 60, 19 + DW 0, 127 + DW 9, 7 + DW 25, 27, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqMHBL DW 14 + DB 60, 20 + DW 0, 127 + DW 9, 8 + DW 26, 28, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqMHBR DW 14 + DB 60, 21 + DW 0, 127 + DW 9, 9 + DW 27, 29, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqMHBF DW 14 + DB 60, 22 + DW 0, 127 + DW 9, 10 + DW 28, 30, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqHBL DW 14 + DB 60, 23 + DW 0, 127 + DW 9, 11 + DW 29, 31, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqHBR DW 14 + DB 60, 24 + DW 0, 127 + DW 9, 12 + DW 30, 32, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqHBF DW 14 + DB 60, 25 + DW 0, 127 + DW 9, 13 + DW 31, 33, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EchoLevel DW 14 + DB 60, 26 + DW 0, 127 + DW 9, 15 + DW 32, 34, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EchoTime DW 14 + DB 60, 27 + DW 0, 127 + DW 9, 14 + DW 33, 35, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EchoFeedback DW 14 + DB 60, 28 + DW 0, 127 + DW 9, 16 + DW 34, 36, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +SurroundVolume DW 14 + DB 60, 29 + DW 0, 255 + DW 9, 17 + DW 35, 37, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +SurroundDelay DW 14 + DB 60, 30 + DW 0, 127 + DW 9, 18 + DW 36, 38, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ReverbSend DW 14 + DB 60, 31 + DW 0, 127 + DW 9, 19 + DW 37, 39, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ReverbVolume DW 14 + DB 60, 32 + DW 0, 255 + DW 9, 20 + DW 38, 40, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + + +ReverbType DW 14 + DB 60, 33 + DW 0, 7 + DW 9, 21 + DW 39, 41, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ReverbTime DW 14 + DB 60, 34 + DW 0, 127 + DW 9, 22 + DW 40, 42, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ReverbFeedback DW 14 + DB 60, 35 + DW 0, 127 + DW 9, 23 + DW 41, 43, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ChorusSend DW 14 + DB 60, 36 + DW 0, 127 + DW 9, 24 + DW 42, 44, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ChorusVolume DW 14 + DB 60, 37 + DW 0, 255 + DW 9, 25 + DW 43, 45, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ChorusType DW 14 + DB 60, 38 + DW 0, 7 + DW 9, 26 + DW 44, 46, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ChorusDelay DW 14 + DB 60, 39 + DW 0, 127 + DW 9, 27 + DW 45, 47, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ChorusFeedback DW 14 + DB 60, 40 + DW 0, 127 + DW 9, 28 + DW 46, 48, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ChorusRate DW 14 + DB 60, 41 + DW 0, 127 + DW 9, 29 + DW 47, 49, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ChorusDepth DW 14 + DB 60, 42 + DW 0, 127 + DW 9, 30 + DW 48, 0FFFFh, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +SAM9407ParametersBox DW 0 + DB 59, 13, 75, 43 + DB 25 + +EmptyObject DW 1 + DB 0, 0 + DB 0 + DB 0 + +SAM9407PortText DW 1 + DB 21, 47 + DB 21h + DB "Audiosystem EWS64 SAM9407 Port ", 0FDh, "Xh, Mixing Rate: ", 0FDh, "D", 0 +MixSpeed DW 48000 +SAM9407Port DW 0 + +DriverText DW 1 + DB 21, 48 + DB 21h + DB "Audiosystem EWS64 XL Codec Driver 1.2 for Impulse Tracker", 0 + +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +IdleFunctionList DD 0 + DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +VolumeText DW 1 + DB 2, 14 + DB 20h + DB "Master Volume Left", 13 + DB "Master Volume Right", 0 + +VolumeBox1 DW 0 + DB 21, 13, 31, 16 + DB 25 + +MasterVolumeLeft DW 9 + DB 22, 14 + DW 0, 63 + DW 9, 0 + DW 0FFFFh, 17, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +MasterVolumeRight DW 9 + DB 22, 15 + DW 0, 63 + DW 9, 1 + DW 16, 6, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +MixModeText DW 1 + DB 2, 18 + DB 20h + DB "Mixing Mode", 0 + +MixModeButton1 DW 2 + DW 17, 7, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment1 DW 0 + DW 0 + DW Offset SetMixMode +DriverSegment2 DW 0 + DB 3, 21, 32, 23, 8 + DB 0 + DB " MMX, Non-interpolated", 0 + +MixModeButton2 DW 2 + DW 6 + DW 8, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment3 DW 0 + DW 1 + DW Offset SetMixMode +DriverSegment4 DW 0 + DB 3, 24, 32, 26, 8 + DB 0 + DB " MMX, Interpolated", 0 + +MixModeButton3 DW 2 + DW 7, 9, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment5 DW 0 + DW 2 + DW Offset SetMixMode +DriverSegment6 DW 0 + DB 3, 27, 32, 29, 8 + DB 0 + DB " MMX, Volume Ramp", 0 + +MixModeButton4 DW 2 + DW 8, 21, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment7 DW 0 + DW 3 + DW Offset SetMixMode +DriverSegment8 DW 0 + DB 3, 30, 32, 32, 8 + DB 0 + DB " MMX, Filtered", 0 + +LongMixSpeed DD 0 + +; ÄÄ MixingRoutines ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include dmasirq.inc +include mix.inc + +include m32bitm.mix +include m32bitmi.mix +include m32bitmv.mix +include m32bitmf.mix + +ALIGN 2 + +MixFunctionTables Label +include m32bitm.inc +include m32bitmi.inc +include m32bitmv.inc +include m32bitmf.inc +include mnomix.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +RelocationTable Label Word + DW Offset DriverSegment1, Offset DriverSegment2 + DW Offset DriverSegment3, Offset DriverSegment4 + DW Offset DriverSegment5, Offset DriverSegment6 + DW Offset DriverSegment7, Offset DriverSegment8 + DW 0 + +; ÄÄ SAM9407InByte ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SAM9407InByte ; Returns AL + + Push DX + Mov DX, CS:SAM9407Port + Inc DX + +SAM9407InByte1: + In AL, DX + Test AL, AL + JS SAM9407InByte1 + + Dec DX + In AL, DX + Pop DX + + Ret + +EndP SAM9407InByte + +Comment ~ + +; ÄÄ ST97InWord ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SAM9407InWord ; Returns AX + + ClI + + Call SAM9407InByte + Mov AL, AH + + Call SAM9407InByte + XChg AL, AH + + StI + + Ret + +EndP SAM9407InWord + +; ÄÄ SAM9407InDWord ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SAM9407InDWord ; Returns EAX + + ClI + + Call SAM9407InByte + RoR EAX, 8 + + Call SAM9407InByte + RoR EAX, 8 + + Call SAM9407InByte + RoR EAX, 8 + + Call SAM9407InByte + RoR EAX, 8 + + StI + Ret + +EndP SAM9407InDWord + +~ + +; ÄÄ ST97SendByte ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SAM9407SendByte ; DX = port, AL = data + + Push AX + Push DX + Mov DX, CS:SAM9407Port + Inc DX + +SAM9407SendByte1: + In AL, DX + Test AL, 40h + JNZ SAM9407SendByte1 + + Pop DX + Pop AX + + Out DX, AL + + Ret + +EndP SAM9407SendByte + +Comment ~ + +; ÄÄ ST97OutByte ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SAM9407OutByte ; AL = data, AH = command, destroys AX + + ClI + Push DX + + Mov DX, CS:SAM9407Port + Inc DX + + XChg AH, AL + Call SAM9407SendByte + + Dec DX + + Mov AL, AH + Call SAM9407SendByte + + Pop DX + StI + + Ret + +EndP SAM9407OutByte + +; ÄÄ ST97OutWord ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SAM9407OutWord ; AX = data, BL = command, destroys AX + + ClI + Push DX + Push AX + + Mov DX, CS:SAM9407Port + Mov AL, BL + Inc DX + Call SAM9407SendByte + + Pop AX + Dec DX + Call SAM9407SendByte + + Mov AL, AH + Call SAM9407SendByte + + Pop DX + StI + + Ret + +EndP SAM9407OutWord + +; ÄÄ ST97OutDWord ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SAM9407OutDWord ; EAX = data, BL = command + + ClI + Push DX + Push AX + + Mov DX, CS:SAM9407Port + Mov AL, BL + Inc DX + Call SAM9407SendByte + + Pop AX + Dec DX + Call SAM9407SendByte + + ShR EAX, 8 + Call SAM9407SendByte + + ShR EAX, 8 + Call SAM9407SendByte + + ShR EAX, 8 + Call SAM9407SendByte + + Pop DX + StI + + Ret + +EndP SAM9407OutDWord + +~ + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetSAM9407 ; DI = index. 1 = full reinit. + + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + LEA SI, [SAM9407Strings+EDI+EDI-2] + Mov SI, [SI] + + LodsW + Mov CX, AX + +SetSAM9407_1: +; AH = 0 = normal data, 1 = command, 2 = param, 3 = ack. + + Mov DX, SAM9407Port + LodsW + + Cmp AH, 2 + JB SetSAM9407_3 + JA SetSAM9407_4 + + Mov AL, [VolumeTable+DI] + Jmp SetSAM9407_2 + +SetSAM9407_4: + Push CX + + Mov CX, 1024 + +SetSAM9407_6: + Call SAM9407InByte + Test AL, AL + LoopNZ SetSAM9407_6 + + Pop CX + + Jmp SetSAM9407_5 + +SetSAM9407_3: + And AH, 1 + Add DL, AH + +SetSAM9407_2: + Call SAM9407SendByte + +SetSAM9407_5: + Dec CX + JNZ SetSAM9407_1 + + Pop DS + PopA + + Ret + +EndP SetSAM9407 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixMode Far + + Push CS + Pop ES + Mov DI, Offset MixMode + + Ret + +EndP GetMixMode + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WaitCoDec + + Push CX + + Mov CX, 0F000h + +WaitCoDec1: + In AL, DX + Test AL, AL + JNS WaitCoDec2 + Loop WaitCoDec1 + + StC + +WaitCoDec2: + Pop CX + Ret + +EndP WaitCoDec + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WaitAutoCalibration + + Push CX + Mov CX, 0F000h + +WaitAutoCalibration1: + Mov AL, CODEC_INDEX_TEST + Out DX, AL + Inc DX + In AL, DX + Dec DX + Test AL, TEST_ACI + JNZ WaitAutoCalibration2 + Loop WaitAutoCalibration1 + + StC + +WaitAutoCalibration2: + Pop CX + Ret + +EndP WaitAutoCalibration + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixMode Far + + Mov AX, [SI+22] + + ClI + + Mov CS:MixMode, AX + + Mov BX, 60 + Mul BX + Mov CS:MixModeOffset, AX + + StI + Mov AX, 1 + Ret + +EndP SetMixMode + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetWSSMixConst ; Work out value.. and nearest + ; mixspeed value. + + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, CmdLineMixSpeed + Mov CX, MixSpeed + Test AX, AX + JZ GetWSSMixConst1 + + Mov CX, 48000 + Cmp AX, CX + JA GetWSSMixConst1 + + Mov CX, 8000 + Cmp AX, CX + JB GetWSSMixConst1 + + Mov CX, AX + +GetWSSMixConst1: ; CX = desired mixspeed + Mov SI, Offset MixSpeedTable + Mov DX, 14 ; 14 different available speeds + + Xor BX, BX + +GetWSSMixConst2: + LodsW + Cmp AX, BX + JB GetWSSMixConst3 + Cmp AX, CX + JA GetWSSMixConst3 + + Mov BX, AX + Mov DH, [SI] + +GetWSSMixConst3: + LodsW ; Add SI, 2 + Dec DL + JNZ GetWSSMixConst2 + + Mov MixSpeed, BX + Mov Word Ptr LongMixSpeed, BX + Mov WSSMixConst, DH + + FNInit + FILd DWord Ptr [MixSpeed] + FMul FreqMultiplier + FStP FreqMultiplier + + Pop DS + PopA + Ret + +EndP GetWSSMixConst + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PingWSS ; Check BasePort, DX = BasePort + ; Preserves DX, destroys AX + + Push DX + + Inc DX + Inc DX + + In AL, DX + Xor AL, AL + Out DX, AL + + Dec DX + Dec DX + Call WaitCodec + JC PingWSSFailure + + In AL, DX + Test AL, AL + JS PingWSSFailure + + Mov AL, CODEC_INDEX_MISC + Out DX, AL + Inc DX ; DX = Data port + In AL, DX + Mov AH, AL ; AH = Revision + + Xor AL, AL ; Write 0 revision + Out DX, AL + In AL, DX + And AX, 8F8Fh + Cmp AL, AH + JNE PingWSSFailure + Dec DX ; DX = AD1848 baseport + + Mov AL, CODEC_MCE or CODEC_INDEX_INTF + Out DX, AL + Inc DX + Mov AL, INTF_ACAL or INTF_SDC + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_INTF + Out DX, AL + Inc DX + Mov AL, INTF_ACAL or INTF_SDC + Out DX, AL + Dec DX + + Call WaitAutoCalibration ; Returns carry if error + ; Carry clear if none. + +; JC PingWSSFailure + + Pop DX + Ret + +PingWSSFailure: + Pop DX + + StC + Ret + + +EndP PingWSS + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +PnP_SerialID DD 0 +PnP_VendorID DD 0 +PnP_ReadPort DW 0 +PnP_CSN DB 0 +PnP_CardFound DB 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectMMX + + Trace "Detecting MMX" + + PushFD + Pop EAX + Mov EBX, EAX + Xor EAX, 00200000h + Push EAX + PopFD + PushFD + Pop EAX + Cmp EAX, EBX + JZ DetectMMXFail + + Mov EAX, 1 + DB 0Fh, 0A2h ; CPUID + Test EDX, 800000h + JZ DetectMMXFail + + Trace "MMX Detected" + + ClC + Ret + +DetectMMXFail: + Trace "MMX not detected" + + StC + Ret + +EndP DetectMMX + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_Delay + Assume DS:Driver + + Push AX CX + + Mov CX, 180h +PnP_Delay1: + In AL, 21h + Loop PnP_Delay1 + + Pop CX AX + Ret + +EndP PnP_Delay + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_WriteData + + Mov DX, 279h + Out DX, AL + + Mov AL, AH + Mov DH, 0Ah + Out DX, AL + Ret + +EndP PnP_WriteData + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_ReadData + + Mov DX, 279h + Out DX, AL + + Mov DX, PnP_ReadPort + In AL, DX + + Ret + +EndP PnP_ReadData + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_Isolate + + Mov AX, 402h + Call Pnp_WriteData ; Reset CSNs + +PnP_IsolateNextCard: + Mov AX, 0003h + Call PnP_WriteData ; Wake[0] + + Mov AX, PnP_ReadPort + ShL AX, 6 + Xor AL, AL + Call PnP_WriteData ; Set Read Data port. + + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + + Mov AL, 1 ; Serial Isolation + Mov DX, 279h + Out DX, AL + + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + + Mov BL, 6Ah + Mov CX, 64 + Mov DX, PnP_ReadPort + + ClI + +PnP_Isolate1: + ShR PnP_SerialID, 1 + RCR PnP_VendorID, 1 + + Mov BH, BL + ShR BH, 1 + Xor BH, BL + ShR BX, 1 + + In AL, DX + Mov AH, AL + Call PnP_Delay + In AL, DX + Call PnP_Delay + + Cmp AX, 55AAh + JNE PnP_Isolate2 + + Xor BL, 80h + Or PnP_SerialID, 80000000h + +PnP_Isolate2: + Dec CX + JNZ PnP_Isolate1 + + Mov CX, 8 + Xor BH, BH + +PnP_Isolate3: + ShR BH, 1 + + In AL, DX + Mov AH, AL + Call PnP_Delay + In AL, DX + Call PnP_Delay + Cmp AX, 55AAh + JNE PnP_Isolate4 + + Or BH, 80h + +PnP_Isolate4: + Dec CX + JNZ PnP_Isolate3 + + StI + + Cmp BL, BH ; Matching Checksum? + JNE PnP_IsolateFinished + + ; assign CSN + Inc PnP_CSN + + Mov AL, 6 + MOv AH, PnP_CSN + Call PnP_WriteData + + Cmp PnP_VendorID, PNPVENDORID + JNE PnP_IsolateNextCard +; Cmp PnP_SerialID, PNPSERIALID +; JNE PnP_IsolateNextCard + + Mov AL, 3 + Call PnP_WriteData + + Mov AX, 07h ; Configuration device + Call PnP_WriteData + + Mov AL, 60h + Call PnP_ReadData + Mov AH, AL + Mov AL, 61h + Call PnP_ReadData ; AX = address. + + Test AX, AX + JZ PnP_IsolateNextCard + + Cmp BasePort, 0FFFFh + JE PnPBasePortOK + + Cmp BasePort, AX + JNE PnP_IsolateNextCard + +PnPBasePortOK: + Mov BasePort, AX + + Mov AL, 70h + Call PnP_ReadData ; AL[3:0] = IRQ + And AX, 15 + JZ PnP_IsolateNextCard + Mov IRQ, AX + + Mov AL, 74h + Call PnP_ReadData ; AL[2:0] = DMA + And AX, 7 + Cmp AL, 4 + JE PnP_IsolateNextCard + Mov DMA, AX + + Mov AX, 407h ; Configuration device + Call PnP_WriteData + + Mov AL, 60h + Call PnP_ReadData + Mov AH, AL + Mov AL, 61h + Call PnP_ReadData ; AX = address. + Test AX, AX + JZ PnP_IsolateNextCard + + Mov SAM9407Port, AX + + Mov Pnp_CardFound, 1 + Jmp PnP_IsolateNextCard + +PnP_IsolateFinished: + Mov AL, PnP_CSN + ShL AL, 1 + Or AL, PnP_CardFound + + Ret + +EndP PnP_Isolate + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far ; returns carry clear if succesful + + Call DetectMMX + JNC DetectCard1 + + Ret + +DetectCard1: + Trace "Detecting EWS64XL" + + Push CS + Pop DS + + Xor AL, AL + Mov DX, 279h + Out DX, AL + Out DX, AL + + Mov AL, 6Ah ; Starting value + Mov CX, 32 + +PnP_InitiationKeyLoop: + Out DX, AL + + Mov AH, AL + ShR AH, 1 + Xor AH, AL + ShR AX, 1 + + Dec CX + JNZ PnP_InitiationKeyLoop + +; Try three ports before concluding no PnP cards: 20Fh, 27Bh, 213h + +PnP_DetectCardPort1: + Mov PnP_ReadPort, 20Fh + Call PnP_Isolate + JZ PnP_DetectCardPort2 + Test AL, 1 + JZ PnP_DetectCardNotFound + Jmp PnP_DetectCardFound + +PnP_DetectCardPort2: + Mov PnP_ReadPort, 27Bh + Call PnP_Isolate + JZ PnP_DetectCardPort3 + Test AL, 1 + JZ PnP_DetectCardNotFound + Jmp PnP_DetectCardFound + +PnP_DetectCardPort3: + Mov PnP_ReadPort, 213h + Call PnP_Isolate + Test AL, 1 + JNZ PnP_DetectCardFound + +PnP_DetectCardNotFound: + Trace "EWS64XL Not Found" + + StC + Jmp PnP_DetectEnd + +PnP_DetectCardFound: + Trace "EWS64XL Found" + ClC + +PnP_DetectEnd: ; Return PnP to wait for key state + Mov AX, 202h + Call PnP_WriteData + Mov EAX, 'Jeff' + + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include mmxmsam.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WSSIRQHandler + + PushAD + Push DS + Push ES + + ClD + + Mov AX, CS + Mov DS, AX + Assume DS:Driver + + Mov DX, [BasePort] + Add DX, 2 + In AL, DX + Test AL, 1 + JZ WSSAckIRQ2 + + Xor AL, AL + Out DX, AL + +WSSAckIRQ2: + Mov AL, 20h + Cmp IRQ, 8 + JB WSSAckIRQ1 + + Out 0A0h, AL + +WSSAckIRQ1: + Out 20h, AL + +DMAPort1 EQU $+1 + In AL, 1 + Mov BL, AL +DMAPort2 EQU $+1 + In AL, 1 + Mov BH, AL + + Xor AX, AX + + Cmp BX, DMABUFFERLENGTH/2 + JB WSSIRQHandler1 + + Mov AX, DMABUFFERLENGTH/2 + +WSSIRQHandler1: + CLD + ; OK... time to get next block + ; Check whether stereo thing is on.. + ; + LES DI, [ActualDMAPtr] + Add DI, AX + + Mov BX, DMASize ; BX = bytes required + ShR BX, 1 + ; BX = samples required + Mov BP, 8 ; Skip for mono + Mov CL, 14 ; Shift for mono + + Cmp Stereo, 0 + JE WSSIRQHandlerMono + + Mov BP, 4 ; Stereo skip value. + Dec CL + +WSSIRQHandlerMono: + Call SaveEMSPageFrame + + Cmp MixTransferRemaining, 0 + JNE WSSIRQHandler4 + Assume DS:Nothing + +WSSIRQHandler3: + Push BX + Push CX + Push BP + Push ES + Push DI + + Call Update + Call MixSamples + + Pop DI + Pop ES + Pop BP + Pop CX + Pop BX + +WSSIRQHandler4: + Mov DS, MixSegment + Mov SI, MixTransferOffset + Mov DX, BX ; DX = samples to transfer + Cmp DX, MixTransferRemaining + JBE WSSIRQHandler5 + + Mov DX, MixTransferRemaining + +WSSIRQHandler5: + +include mmxtrans.inc + + Sub MixTransferRemaining, DX ; } Memory write + Sub BX, DX + JNZ WSSIRQHandler3 + + Mov MixTransferOffset, SI ; } Memory write + + Call RestoreEMSPageFrame + + Pop ES + Pop DS + PopAD + IRet + +EndP WSSIRQHandler + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Add DI, Offset IRQData + Mov BX, [CS:DI] + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset WSSIRQHandler + + XChg [ES:BX], EAX + Mov OldWSSIRQHandler, EAX + + Mov AX, IMR + And AX, [DI+2] + + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Pop ES + PopAD + + Ret + +EndP SetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Mov BX, [IRQData+DI] + + Mov EAX, OldWSSIRQHandler + Mov [ES:BX], EAX + + Pop ES + PopAD + + Ret + +EndP ResetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StopWSS + + Mov DX, BasePort + + Mov AL, CODEC_INDEX_INTF + Out DX, AL + Inc DX + In AL, DX + And AL, Not INTF_PEN + Out DX, AL + + Inc DX + In AL, DX + Xor AL, AL + Out DX, AL + + Dec DX + Dec DX + + Mov AL, CODEC_INDEX_PIN + Out DX, AL + Inc DX + Xor AL, AL + Out DX, AL + + Ret + +EndP StopWSS + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StartWSS + + PushA + Push ES + Push DS + + Push CS + Pop DS + Assume DS:Driver + + ; Setup DMA + Mov BX, MixSegment + Mov AX, 80 + Mov DX, DMA + Mov DI, DMABUFFERLENGTH + Call SetDMA + + LES DI, ActualDMAPtr + Xor AX, AX + Mov CX, DMABUFFERLENGTH/2 + Rep StosW + + Mov MixTransferRemaining, 0 + + Mov DX, BasePort + Call PingWSS + + Mov AL, CODEC_INDEX_PIN + Out DX, AL + Inc DX + Mov AL, PIN_IEN + Out DX, AL + Dec DX + + Mov AH, WSSMixConst ; Set format/frequency + Cmp Stereo, 0 + JE StartWSS1 + + Or AH, CDF_STEREO + +StartWSS1: + Mov AL, CODEC_MCE or CODEC_INDEX_CDF + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Call WaitCodec + + Mov AL, CODEC_INDEX_CDF + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Call WaitAutoCalibration + + ; Start playback + Mov AL, CODEC_INDEX_LWR_COUNT + Out DX, AL + Inc DX + + Mov AX, DMASize + ShR AX, 1 + + Cmp Stereo, 0 + JE StartWSS2 + + ShR AX, 1 + +StartWSS2: + Dec AX + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_UPR_COUNT + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_INTF + Out DX, AL + Inc DX + In AL, DX + Or AL, INTF_PEN + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_LDC + Out DX, AL + Inc DX + In AL, DX + And AL, Not LDC_LDM + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_RDC + Out DX, AL + Inc DX + In AL, DX + And AL, Not RDC_RDM + Out DX, AL + Dec DX + + Pop DS + Pop ES + PopA + + Ret + +EndP StartWSS + Assume DS:Nothing + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Trace "EWS64XL InitSound" + + Push CS + Pop DS + Assume DS:Driver + + Mov SI, Offset RelocationTable + +RelocationFix: + LodsW + Test AX, AX + JZ RelocationEnd + Mov BX, AX + Mov [BX], DS + Jmp RelocationFix + + +RelocationEnd: + Call GetEMSPageFrame + Mov EMSPageFrame, AX + + In AL, 0A1h + Mov AH, AL + In AL, 21h + Mov IMR, AX + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + Call GetWSSMixConst + + Mov AX, 2643 + Mul MixSpeed + Add AX, 0FFFFh + AdC DX, 5 + (DMABUFFERLENGTH*2)/16 + Mov BX, DX + + ; Allocate MixSegment first + Mov AH, 48h + + Int 21h + JNC InitSound1 + +InitSoundNoMemory: + Mov SI, Offset WSSNoMemoryMsg + Ret + +InitSound1: + Mov MixSegment, AX + + Trace "EWS64XL Memory Allocated" + + Call SetIRQ + Call GetTempo + Call SetTempo + + Trace "EWS64XL IRQ Hooked" + + Mov DX, BasePort + Mov AL, CODEC_INDEX_RDC + Out DX, AL + Inc DX + In AL, DX + Mov AH, AL + Dec DX + + Mov AL, CODEC_INDEX_LDC + Out DX, AL + Inc DX + In AL, DX + And AX, 3F3Fh + Neg AL + Neg AH + Add AL, 3Fh + Add AH, 3Fh + Mov [Word Ptr VolumeTable], AX + + Trace "EWS64XL Volume Settings Received" + + Mov DI, 1 + Call SetSAM9407 + + Trace "EWS64XL SAM9407 InitString finished" + + Mov SI, Offset WSSMsg + + Mov AX, BasePort + Mov BX, IRQ + Mov CX, DMA + + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Call StopWSS + Call ResetIRQ + Call SetIRQ + + Mov SI, Offset ReInitMsg + Mov BX, 40 + Call SetInfoLine + + Mov AL, Stereo + Call SetStereo + + Pop ES + Pop DS + PopA + + Ret + +EndP ReInitSound + Assume DS:Nothing + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, IMR + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Mov AX, MixSegment + Test AX, AX + JZ UnInitSound1 + + Mov ES, AX + Mov AH, 49h ; Release MixSegment + Int 21h + + Call StopWSS + Call ResetIRQ + +UnInitSound1: + Call GotoHomeDirectory + + ; Now to save config into driver file. + Mov AX, 3D02h ; Read write access + Mov DX, Offset DriverName + Int 21h + JC SetMixMode1 + + Mov BX, AX + + Mov AX, 4200h + Xor CX, CX + Mov DX, Offset CONFIGURATIONOFFSET + Int 21h + JC SetMixMode2 + + Mov AH, 40h + Mov CX, CONFIGSIZE + Mov DX, Offset MixMode + Int 21h + +SetMixMode2: + Mov AH, 3Eh + Int 21h + +SetMixMode1: + Ret + +EndP UnInitSound + Assume DS:Nothing + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + Ret + +EndP Poll + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Push AX + Push BX + Push DX + + Push BX + + Mov AX, MixSpeed + Mov BX, AX + Xor DX, DX + + ShL AX, 1 + RCL DX, 1 ; DX:AX = Mixspeed*2 + + ShR BX, 1 ; BX = Mixspeed/2 + + Add AX, BX + AdC DX, 0 ; DX:AX = Mixspeed*2.5 + + Pop BX ; BX = tempo + Div BX + + Mov BytesToMix, AX + + Pop DX + Pop BX + Pop AX + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + Mov CS:MixVolume, AX + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Jmp CS:RecalculateAllVolumes + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc RecalculateAllFrequencies + + Call GetChannelTables + +RecalculateAllFrequencies1: + Or Byte Ptr [SI], 32 + + Add SI, 128 + Dec CX + JNZ RecalculateAllFrequencies1 + + Ret + +EndP RecalculateAllFrequencies + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Mov CS:Stereo, AL + Cmp CS:MixSegment, 0 + JE SetStereo1 + + Push AX + + Call StopWSS + Call StartWSS + + Call RecalculateAllFrequencies + + Pop DI + + And DI, 1 + Add DI, 31 + Call SetSAM9407 + + Mov DI, 2 +SetStereo2: + Call SetSAM9407 + Inc DI + Cmp DI, 30 + JBE SetStereo2 + +SetStereo1: + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include loadsam.inc + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset WSS16ScreenList + + ClC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far + + Xor AH, AH + Mov AL, [CS:VolumeTable+DI] + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UpdateSoundcardVariables + + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov DX, BasePort + + Mov AL, CODEC_INDEX_LDC + Out DX, AL + Inc DX + Mov AX, 3F3Fh + Sub AX, [Word Ptr VolumeTable] + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_RDC + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + + Pop DS + PopA + + Ret + +EndP UpdateSoundcardVariables + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far + + Mov [CS:VolumeTable+DI], AL + Cmp DI, 2 + JB SetVariable1 + + Call SetSAM9407 + Ret + +SetVariable1: + Call UpdateSoundcardVariables + Ret + +EndP SetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UARTOut + + Push CX + Push DX + Mov DX, CS:SAM9407Port + + Push AX + Xor CX, CX + Inc DX + +UARTOut1: + In AL, DX + Test AL, 40h + LoopNZ UARTOut1 + + Pop AX + JNZ UARTOutEnd + + Dec DX + Out DX, AL + +UARTOutEnd: + Pop DX + Pop CX + + Ret + +EndP UARTOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +InterpretState DB 0 +InterpretType DB 0 + +Proc SendUARTOut Far ; Local interpreter activated with 0F0h 0F0h. + + Mov AH, CS:InterpretState + Cmp AH, 2 + JB SendUARTOut1 + +; In interpreter. + JE SendUARTOut3 + +; Have InterpretType, now get parameter, then return to normal. + + Cmp AL, 7Fh + JA SendUARTOut4 + + Push BX + + Mov BL, CS:InterpretType ; Want BX = InterpretType*64+Channel + ; + ShL BX, 6 + Add BL, [DI+20h] + And BX, 127 + Mov [CS:FilterParameters+BX], AL + + Pop BX + + Test SI, SI + JZ SendUARTOut4 + + Or Byte Ptr [SI], 64 + +SendUARTOut4: + Mov CS:InterpretState, 0 + Ret + +SendUARTOut3: + Cmp AL, 2 + JAE SendUARTOut4 + + Mov CS:InterpretType, AL + Jmp SendUARTOutStateInc + +SendUARTOut1: + Cmp AL, 0F0h + JNE SendUARTOut2 + +SendUARTOutStateInc: + Inc CS:InterpretState + Ret + +SendUARTOut2: + Test AH, AH + JZ SendUARTOutEnd + + Push AX + Mov AL, 0F0h + Call UARTOut + Pop AX + Mov CS:InterpretState, 0 + +SendUARTOutEnd: + Cmp AL, 0FCh + JE ResetFilters + Cmp AL, 0FAh + JE ResetFilters + + Cmp AL, 0FFh + JNE SendUARTOutNoClear + +ResetFilters: + PushA + Push ES + + Push CS + Pop ES + + Mov DI, Offset FilterParameters + Mov CX, 64 + Mov AL, 7Fh + Rep StosB + Mov CX, 64 + Xor AX, AX + Rep StosB + + Pop ES + PopA + +SendUARTOutNoClear: + Call UARTOut + Ret + +EndP SendUARTOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. + +StopAfterPlay DW 0 +DefaultChannels DW 128 +DriverFlags DW 3 + DW 4 Dup (0) + + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + DW Offset SendUARTOut + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/EXECOM.COM b/SoundDrivers/EXECOM.COM new file mode 100755 index 0000000..dc99245 Binary files /dev/null and b/SoundDrivers/EXECOM.COM differ diff --git a/SoundDrivers/FOURIER.INC b/SoundDrivers/FOURIER.INC new file mode 100755 index 0000000..0b7fdfb --- /dev/null +++ b/SoundDrivers/FOURIER.INC @@ -0,0 +1,83 @@ + +FourierBufferStart DW 0 + +FourierBufferInputStart DW 0 +FourierBufferInputFractional DW 0 +FourierBufferStepOffset DW 1 +FourierBufferStepFractional DW 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UpdateFourierBuffer + + PushAD + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Xor EBX, EBX + Xor ESI, ESI + + Mov BX, MixTransferOffset + Mov DI, FourierBufferStart + ShR BX, 3 + Mov CX, BytesToMix + Mov SI, FourierBufferInputStart + Add SI, BX + Add CX, BX + + Mov BP, FourierBufferInputFractional + Mov DX, FourierBufferStepOffset + Mov BX, FourierBufferStepFractional + + Mov ES, FourierSegment + Mov DS, MixSegment + + Assume DS:Nothing + +UpdateFourierBuffer1: + Mov EAX, [ESI*8] + Add EAX, [ESI*8+4] + SAR EAX, 13 + Cmp EAX, 7FFFh + JG UpdateFourierBuffer3 + Cmp EAX, -8000h + JL UpdateFourierBuffer4 + +UpdateFourierBuffer2: + StosW + + Add BP, BX + AdC SI, DX + And DI, (FOURIERBUFFERLENGTH*2)-1 + +; Cmp past end of buffer? + Cmp SI, CX + JB UpdateFourierBuffer1 + + Sub SI, CX + Mov FourierBufferStart, DI + Mov FourierBufferInputFractional, BP + Mov FourierBufferInputStart, SI + + Pop ES + Pop DS + PopAD + + Ret + +UpdateFourierBuffer3: + Mov AX, 7FFFh + Jmp UpdateFourierBuffer2 + +UpdateFourierBuffer4: + Mov AX, 8000h + Jmp UpdateFourierBuffer2 + +EndP UpdateFourierBuffer + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + diff --git a/SoundDrivers/FREQ.INC b/SoundDrivers/FREQ.INC new file mode 100755 index 0000000..1fb4a2b --- /dev/null +++ b/SoundDrivers/FREQ.INC @@ -0,0 +1,34 @@ + +FilterFrequencyTable Label DWord + DD 3A9F7867h, 3A9AEE36h, 3A96851Bh, 3A923C25h + DD 3A8E1269h, 3A8A0703h, 3A861918h, 3A8247CFh + DD 3A7D24B3h, 3A75EFD6h, 3A6EEF7Dh, 3A68222Ch + DD 3A61866Dh, 3A5B1AD6h, 3A54DE0Bh, 3A4ECEB3h + DD 3A48EB87h, 3A433341h, 3A3DA4ACh, 3A383E96h + DD 3A32FFD8h, 3A2DE754h, 3A28F3F3h, 3A2424A6h + DD 3A1F7867h, 3A1AEE36h, 3A16851Bh, 3A123C25h + DD 3A0E1269h, 3A0A0703h, 3A061918h, 3A0247CFh + DD 39FD24B3h, 39F5EFD6h, 39EEEF7Dh, 39E8222Ch + DD 39E1866Dh, 39DB1AD6h, 39D4DE0Bh, 39CECEB3h + DD 39C8EB87h, 39C33341h, 39BDA4ACh, 39B83E96h + DD 39B2FFD8h, 39ADE754h, 39A8F3F3h, 39A424A6h + DD 399F7867h, 399AEE36h, 3996851Bh, 39923C25h + DD 398E1269h, 398A0703h, 39861918h, 398247CFh + DD 397D24B3h, 3975EFD6h, 396EEF7Dh, 3968222Ch + DD 3961866Dh, 395B1AD6h, 3954DE0Bh, 394ECEB3h + DD 3948EB87h, 39433341h, 393DA4ACh, 39383E96h + DD 3932FFD8h, 392DE754h, 3928F3F3h, 392424A6h + DD 391F7867h, 391AEE36h, 3916851Bh, 39123C25h + DD 390E1269h, 390A0703h, 39061918h, 390247CFh + DD 38FD24B3h, 38F5EFD6h, 38EEEF7Dh, 38E8222Ch + DD 38E1866Dh, 38DB1AD6h, 38D4DE0Bh, 38CECEB3h + DD 38C8EB87h, 38C33341h, 38BDA4ACh, 38B83E96h + DD 38B2FFD8h, 38ADE754h, 38A8F3F3h, 38A424A6h + DD 389F7867h, 389AEE36h, 3896851Bh, 38923C25h + DD 388E1269h, 388A0703h, 38861918h, 388247CFh + DD 387D24B3h, 3875EFD6h, 386EEF7Dh, 3868222Ch + DD 3861866Dh, 385B1AD6h, 3854DE0Bh, 384ECEB3h + DD 3848EB87h, 38433341h, 383DA4ACh, 38383E96h + DD 3832FFD8h, 382DE754h, 3828F3F3h, 382424A6h + DD 381F7867h, 381AEE36h, 3816851Bh, 38123C25h + DD 380E1269h, 380A0703h, 38061918h, 380247CFh diff --git a/SoundDrivers/GOLD16.ASM b/SoundDrivers/GOLD16.ASM new file mode 100755 index 0000000..c8f1b55 --- /dev/null +++ b/SoundDrivers/GOLD16.ASM @@ -0,0 +1,2328 @@ +; +; ESS Technology's ES1868 AudioDrive chip. +; + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;********************************** + +PNPSERIALID EQU 0FFFFFFFFh +PNPVENDORID EQU 68187316h + +STEREOENABLED EQU 1 +DMABUFFERLENGTH EQU 8192 +MIXRESOLUTION EQU 32 ; 32 bit mixing for +MIXTABLESIZE EQU 2*256*65 + +ESSMsg DB "ESS ES1868 AudioDrive found", 13 + DB "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, DMA ", 0FDh, "D", 0 + +ESSNoMemoryMsg DB "ESS ES1868 AudioDrive found", 13 + DB "Error: Insufficient memory", 0 + +ReinitMsg DB "ESS ES1868 AudioDrive reinitialised", 0 + +ConfigErrorMsg DB "Error saving configuration to ITES1868.DRV", 0 +ConfigOKMsg DB "Configuration saved to ITES1868.DRV", 0 + +DriverName DB "ITES1868.DRV", 0 + +ALIGN 4 +FilterValue DD 0 +FilterValue2 DD 0 +ESSMixConst DB 0, 0 + +DMASize DW 2048 ; Smaller gives better MIDI timing +ConfigPort DW 0 + +Forced DB 0 +Stereo DB 0 +MixVolume DW 0 + +BytesToMix DW 1000 + +MixSegment DW 0 +DMASegment DW 0 + +MixTransferOffset DW 0 +MixTransferRemaining DW 0 + +CONFIGURATIONOFFSET EQU $+128 +CONFIGSIZE EQU 6 +MixMode DW 0 +MixModeOffset DW 0 +Filter DW 0 + +IMR DW 0 +OldESSIRQHandler DD 0 + +IRQData Label Word + DW 20h, 1111111111111110b ; IRQ 0 + DW 24h, 1111111111111101b ; IRQ 1 + DW 28h, 1111110111111011b ; IRQ 2 + DW 2Ch, 1111111111110111b ; IRQ 3 + DW 30h, 1111111111101111b ; IRQ 4 + DW 34h, 1111111111011111b ; IRQ 5 + DW 38h, 1111111110111111b ; IRQ 6 + DW 3Ch, 1111111101111111b ; IRQ 7 + DW 1C0h, 1111111011111011b ; IRQ 8 + DW 1C4h, 1111110111111011b ; IRQ 9 + DW 1C8h, 1111101111111011b ; IRQ 10 + DW 1CCh, 1111011111111011b ; IRQ 11 + DW 1D0h, 1110111111111011b ; IRQ 12 + DW 1D4h, 1101111111111011b ; IRQ 13 + DW 1D8h, 1011111111111011b ; IRQ 14 + DW 1DCh, 0111111111111011b ; IRQ 15 + +ESSScreenList Label + DW 6 + DW Near Ptr IdleFunctionList + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr ESSHeaderLine + + DW Near Ptr DriverText + + DW Near Ptr MixModeText + DW Near Ptr MixModeButton1 ; 6 + DW Near Ptr MixModeButton2 ; + DW Near Ptr MixModeButton3 ; 8 + DW Near Ptr MixModeButton4 ; 9 + + DW Near Ptr FilterText + DW Near Ptr FilterButton1 ; 11 + DW Near Ptr FilterButton2 + DW Near Ptr FilterButton3 + +Comment ~ + + DW Near Ptr VolumeText + DW Near Ptr VolumeBox1 + + DW Near Ptr MasterVolumeLeft ; 16 + DW Near Ptr MasterVolumeRight ; 17 + +~ + + DW 0 + +ESSHeaderLine DW 10 + DB "ESS ES1868 AudioDrive Driver", 0 + +EmptyObject DW 1 + DB 0, 0 + DB 0 + DB 0 + +DriverText DW 1 + DB 26, 48 + DB 21h + DB "ESS ES1868 AudioDrive Driver 1.0 for Impulse Tracker", 0 + +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +IdleFunctionList DD 0 + DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +Comment ~ + +VolumeText DW 1 + DB 2, 14 + DB 20h + DB "Master Volume Left", 13 + DB "Master Volume Right" + DB 0 + +VolumeBox1 DW 0 + DB 21, 13, 31, 16 + DB 25 + +MasterVolumeLeft DW 14 + DB 22, 14 + DW 0, 15 + DW 9, 0 + DW 0FFFFh, 17, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 8 + +MasterVolumeRight DW 14 + DB 22, 15 + DW 0, 15 + DW 9, 1 + DW 16, 6, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 8 + +~ + +MixModeText DW 1 + DB 2, 14 + DB 20h + DB "Mixing Mode, Playback Frequency: ", 0FDh, "DHz", 0 +MixSpeed DW 44100 + +MixModeButton1 DW 2 + DW 0FFFFh, 7, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment1 DW 0 + DW 0 + DW Offset SetMixMode +DriverSegment2 DW 0 + DB 3, 16, 32, 18, 8 + DB 0 + DB " 16 Bit, Non-Interpolated", 0 + +MixModeButton2 DW 2 + DW 6, 8, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment3 DW 0 + DW 2 + DW Offset SetMixMode +DriverSegment4 DW 0 + DB 3, 19, 32, 21, 8 + DB 0 + DB " 16 Bit, Interpolated", 0 + +MixModeButton3 DW 2 + DW 7, 9, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment5 DW 0 + DW 4 + DW Offset SetMixMode +DriverSegment6 DW 0 + DB 3, 22, 32, 24, 8 + DB 0 + DB " 32 Bit, Non-Interpolated", 0 + +MixModeButton4 DW 2 + DW 8, 11, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment7 DW 0 + DW 6 + DW Offset SetMixMode +DriverSegment8 DW 0 + DB 3, 25, 32, 27, 8 + DB 0 + DB " 32 Bit, Interpolated", 0 + +FilterText DW 1 + DB 2, 29 + DB 20h + DB "Filter mode", 0 + +FilterButton1 DW 2 + DW 9, 12, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment9 DW 0 + DW 0 + DW Offset SetFilter +DriverSegment10 DW 0 + DB 3, 31, 29, 33, 8 + DB 0 + DB " No Filter", 0 + +FilterButton2 DW 2 + DW 11, 13, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment11 DW 0 + DW 1 + DW Offset SetFilter +DriverSegment12 DW 0 + DB 3, 34, 29, 36, 8 + DB 0 + DB " 50% Filter", 0 + +FilterButton3 DW 2 + DW 12, 0FFFFh, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment13 DW 0 + DW 2 + DW Offset SetFilter +DriverSegment14 DW 0 + DB 3, 37, 29, 39, 8 + DB 0 + DB " 75% Filter", 0 + +ALIGN 4 + +VolumeTable DB 2 Dup (0) +MIDIPort DW 0 + +MIDIBuffer DB 256 Dup (0) +MIDIBufferHead DB 0 +MIDIBufferTail DB 0 + +; ÄÄ MixingRoutines ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixBufferPos DW 0 + +include dma.inc +include mix.inc +include m12bit.mix +include m12biti.mix +include m32bit.mix +include m32biti.mix + +MixFunctionTables Label + +include m12bit.inc ; contains the tables +include m12biti.inc +include m32bit.inc +include m32biti.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +RelocationTable Label Word + DW Offset DriverSegment1, Offset DriverSegment2 + DW Offset DriverSegment3, Offset DriverSegment4 + DW Offset DriverSegment5, Offset DriverSegment6 + DW Offset DriverSegment7, Offset DriverSegment8 + DW Offset DriverSegment9, Offset DriverSegment10 + DW Offset DriverSegment11, Offset DriverSegment12 + DW Offset DriverSegment13, Offset DriverSegment14 + DW 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ESSOut ; AL = data + ; DX = 2xCh + + Push AX + +ESSOut1: + In AL, DX + Test AL, AL + JS ESSOut1 + + Pop AX + Out DX, AL + + Ret + +EndP ESSOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ESSIn ; DX = 2xCh, returns AL + +ESSIn1: + In AL, DX + Test AL, 40h + JZ ESSIn1 + + Add DL, 0Ah-0Ch ; DX = 2xAh -> Data read port + In AL, DX + Add DL, 0Ch-0Ah + + Ret + +EndP ESSIn + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UARTOut ; AL = out + + Push DX + Push AX + + Mov DX, CS:MIDIPort + Inc DX + +UARTOut1: + In AL, DX + Test AL, 40h + JNZ UARTOut1 + + Pop AX + Dec DX + Out DX, AL + + Pop DX + Ret + +EndP UARTOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UARTIn ; returns AL + + Push DX + + Mov DX, CS:MIDIPort + Inc DX + +UARTIn1: + In AL, DX + Test AL, 80h + JNZ UARTIn1 + + Dec DX + In AL, DX + + Pop DX + Ret + +EndP UARTIn + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ESSReadRegister ; AH = register to read. + ; DX = 2xCh + ; returns AL + + Mov AL, 0C0h + Call ESSOut + Mov AL, AH + Call ESSOut + Call ESSIn + + Ret + +EndP ESSReadRegister + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixMode Far + + Push CS + Pop ES + Mov DI, Offset MixMode + + Ret + +EndP GetMixMode + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetFilter Far + + Push CS + Pop ES + Mov DI, Offset Filter + + Ret + +EndP GetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetFilter Far + + Mov AX, [SI+22] + Mov CS:FilterValue, 0 + Mov CS:Filter, AX + ClI + Jmp SetMixModeChain + +EndP SetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixMode Far + + Mov AX, [SI+22] + + ClI + + Mov CS:MixMode, AX + + Mov BX, 180 + Mul BX + Mov CS:MixModeOffset, AX + + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS:RecalculateAllVolumes + + StI + +SetMixModeChain: + Call GotoHomeDirectory + + ; Now to save config into driver file. + Push CS + Pop DS + Assume DS:Driver + + Mov AX, 3D02h ; Read write access + Mov DX, Offset DriverName + Mov SI, Offset ConfigErrorMsg + Int 21h + JC SetMixMode1 + + Mov BX, AX + + Mov AX, 4200h + Xor CX, CX + Mov DX, Offset CONFIGURATIONOFFSET + Int 21h + JC SetMixMode2 + + Mov AH, 40h + Mov CX, CONFIGSIZE + Mov DX, Offset MixMode + Int 21h + +SetMixMode2: + PushF + Mov AH, 3Eh + Int 21h + PopF + + JC SetMixMode1 + + Mov SI, Offset ConfigOKMsg + +SetMixMode1: + Mov BX, 40 + Call SetInfoLine + + Mov AX, 1 + Ret + +EndP SetMixMode + Assume DS:Nothing + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +PnP_SerialID DD 0 +PnP_VendorID DD 0 +PnP_ReadPort DW 0 +PnP_CSN DB 0 +PnP_CardFound DB 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_Delay + Assume DS:Driver + + Push AX CX + + Mov CX, 180h +PnP_Delay1: + In AL, 21h + Loop PnP_Delay1 + + Pop CX AX + Ret + +EndP PnP_Delay + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_WriteData + + Mov DX, 279h + Out DX, AL + + Mov AL, AH + Mov DH, 0Ah + Out DX, AL + Ret + +EndP PnP_WriteData + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_ReadData + + Mov DX, 279h + Out DX, AL + + Mov DX, PnP_ReadPort + In AL, DX + + Ret + +EndP PnP_ReadData + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_Isolate + + Mov AX, 402h + Call Pnp_WriteData ; Reset CSNs + +PnP_IsolateNextCard: + Mov AX, 0003h + Call PnP_WriteData ; Wake[0] + + Mov AX, PnP_ReadPort + ShL AX, 6 + Xor AL, AL + Call PnP_WriteData ; Set Read Data port. + + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + + Mov AL, 1 ; Serial Isolation + Mov DX, 279h + Out DX, AL + + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + + Mov BL, 6Ah + Mov CX, 64 + Mov DX, PnP_ReadPort + + ClI + +PnP_Isolate1: + ShR PnP_SerialID, 1 + RCR PnP_VendorID, 1 + + Mov BH, BL + ShR BH, 1 + Xor BH, BL + ShR BX, 1 + + In AL, DX + Mov AH, AL + Call PnP_Delay + In AL, DX + Call PnP_Delay + + Cmp AX, 55AAh + JNE PnP_Isolate2 + + Xor BL, 80h + Or PnP_SerialID, 80000000h + +PnP_Isolate2: + Dec CX + JNZ PnP_Isolate1 + + Mov CX, 8 + Xor BH, BH + +PnP_Isolate3: + ShR BH, 1 + + In AL, DX + Mov AH, AL + Call PnP_Delay + In AL, DX + Call PnP_Delay + Cmp AX, 55AAh + JNE PnP_Isolate4 + + Or BH, 80h + +PnP_Isolate4: + Dec CX + JNZ PnP_Isolate3 + + StI + + Cmp BL, BH ; Matching Checksum? + JNE PnP_IsolateFinished + + ; assign CSN + Inc PnP_CSN + + Mov AL, 6 + MOv AH, PnP_CSN + Call PnP_WriteData + + Cmp PnP_VendorID, PNPVENDORID + JNE PnP_IsolateNextCard + Cmp PnP_SerialID, PNPSERIALID + JNE PnP_IsolateNextCard + + Mov AL, 3 + Call PnP_WriteData + + Mov AX, 07h ; Configuration device + Call PnP_WriteData + + Mov AL, 60h + Call PnP_ReadData + Mov AH, AL + Mov AL, 61h + Call PnP_ReadData ; AX = address. + Mov ConfigPort, AX + + Mov AX, 107h ; Audio device + Call PnP_WriteData + + Mov AL, 64h + Call PnP_ReadData + Mov AH, AL + Mov AL, 65h + Call PnP_ReadData ; AX = address. + Mov MIDIPort, AX + + Mov AL, 60h + Call PnP_ReadData + Mov AH, AL + Mov AL, 61h + Call PnP_ReadData ; AX = address. + Cmp BasePort, 0FFFFh + JE PnPBasePortOK + + Cmp BasePort, AX + JNE PnP_IsolateNextCard + +PnPBasePortOK: + Mov BasePort, AX + + Mov AL, 70h + Call PnP_ReadData ; AL[3:0] = IRQ + And AX, 15 + JZ PnP_IsolateNextCard + Mov IRQ, AX + + Mov AL, 74h + Call PnP_ReadData ; AL[2:0] = DMA + And AX, 7 + Cmp AL, 4 + JE PnP_IsolateNextCard + Mov DMA, AX + + Mov Pnp_CardFound, 1 + Jmp PnP_IsolateNextCard + +PnP_IsolateFinished: + Mov AL, PnP_CSN + ShL AL, 1 + Or AL, PnP_CardFound + + Ret + +EndP PnP_Isolate + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far ; returns carry clear if succesful + + Push CS + Pop DS + + Xor AL, AL + Mov DX, 279h + Out DX, AL + Out DX, AL + + Mov AL, 6Ah ; Starting value + Mov CX, 32 + +PnP_InitiationKeyLoop: + Out DX, AL + + Mov AH, AL + ShR AH, 1 + Xor AH, AL + ShR AX, 1 + + Dec CX + JNZ PnP_InitiationKeyLoop + +; Try three ports before concluding no PnP cards: 20Fh, 27Bh, 213h + +PnP_DetectCardPort1: + Mov PnP_ReadPort, 20Fh + Call PnP_Isolate + JZ PnP_DetectCardPort2 + Test AL, 1 + JZ PnP_DetectCardNotFound + Jmp PnP_DetectCardFound + +PnP_DetectCardPort2: + Mov PnP_ReadPort, 27Bh + Call PnP_Isolate + JZ PnP_DetectCardPort3 + Test AL, 1 + JZ PnP_DetectCardNotFound + Jmp PnP_DetectCardFound + +PnP_DetectCardPort3: + Mov PnP_ReadPort, 213h + Call PnP_Isolate + Test AL, 1 + JNZ PnP_DetectCardFound + +PnP_DetectCardNotFound: + StC + Jmp PnP_DetectEnd + +PnP_DetectCardFound: + ClC + +PnP_DetectEnd: ; Return PnP to wait for key state + Mov AX, 202h + Call PnP_WriteData + Mov EAX, 'Jeff' + + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetDSP Far ; AX = Port + + Push AX + Push CX + Push DX + + Mov DX, CS:MIDIPort + Inc DX + Mov AL, 0FFh + Out DX, AL + + Mov DX, CS:BasePort + Add DL, 6 + Mov AL, 3 + Out DX, AL + + In AL, DX + In AL, DX + In AL, DX + In AL, DX + + Xor AL, AL + Out DX, AL + + Add DL, 8 + Mov CX, 200 + +ResetDSP1: + In AL, DX + Test AL, AL + JS ResetDSP2 + Loop ResetDSP1 + Jmp ResetDSP3 + +ResetDSP2: + Sub DL, 4 + In AL, DX + Cmp AL, 0AAh + JE ResetDSP4 + Add DL, 4 + Loop ResetDSP1 + +ResetDSP3: + StC + +ResetDSP4: + Pop DX + Pop CX + Pop AX + Ret + +EndP ResetDSP + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixModeTable Label Word + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + +Proc MixSamples ; Given DS:SI = info tables, CX = numchannels + + ; 1. Clean buffer + ; + update variables + ; 2. Update parameters + ; 3. Mix func + ; 4. Return + + Push CX + + Mov CX, BytesToMix + Mov ES, MixSegment + Mov DI, MIXTABLESIZE + Xor EAX, EAX + Mov DX, CX + Add CX, CX + + Mov MixTransferOffset, DI ; } Memory write + + Cmp Stereo, 0 + JE MixSamples1 + + Mov DX, CX + +MixSamples1: + Rep StosD ; } Memory write + Mov MixTransferRemaining, DX ; } + + Pop CX + +MixSamples2: + Test Byte Ptr [SI], 1 + JZ MixSamplesEnd2 + Cmp Byte Ptr [SI+36h], 100 + JE MixSamplesEnd2 + + Push CX + Mov CX, [SI] + + Test CH, 2 + JZ MixSamples3 + And Byte Ptr [SI], Not 1 + + Jmp MixSamplesEnd +; Cmp MixMode, 8 ; Is it volume ramping? +; JB MixSamplesEnd + +MixSamples3: + Test CL, 20h ; New freq? + JZ MixSamples5 + + Mov AX, [SI+10h] + Mov DX, [SI+12h] + Mov BX, MixSpeed + Cmp DX, BX + JAE MixSamplesHandleError + + Div BX + ShL EAX, 16 + Xor AX, AX + Div BX + Mov STEPVALUE, EAX + +MixSamples4: + Test CH, 1 + JZ MixSamples5 + + Mov DWord Ptr [SI+1Ch], 0 ; Current Volume = 0 + ; for volume sliding. +MixSamples5: + Test CX, 8440h ; New volume or panning? + JZ MixSamplesMix + + Xor AX, AX + Test CH, 8 ; Muted? + JNZ MixModeCommon + + Mov BX, MixMode + Add BL, Stereo + Add BX, BX + Jmp [CS:MixModeTable+BX] + +Mix0Mode: ; 16-bit mixing, no interpolation +Mix0ModeMono: ; and 16-bit mixing, interpolation + Mov AL, [SI+20h] + ShR AL, 1 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 30 ; Use left only-mixing for mono + Jmp MixModeCommon + +Mix0ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix0ModeSurround + + Mul Byte Ptr [SI+20h] ; Final volume + Add AX, 64 + ShR AX, 7 + Mov [SI+0Ch], AX ; Store into right volume + + Mov AL, 64 + Sub AL, [SI+37h] + Mul Byte Ptr [SI+20h] + Add AX, 64 + ShR AX, 7 + Mov [SI+0Eh], AX ; Left volume + + Mov CH, AL ; CH = left volume + Mov CL, [SI+0Ch] ; CL = right volume + Mov AX, 0 + + Test CX, CX + JZ MixModeCommon + + Mov AL, 30 ; Left only... + Test CL, CL + JZ MixModeCommon + + Mov AL, 60 + Test CH, CH + JZ MixModeCommon + + Mov AL, 90 + Cmp CL, CH + JZ MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix0ModeSurround: + Mov AL, [SI+20h] + ShR AL, 2 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 150 ; Surround + Jmp MixModeCommon + +Mix6ModeMono: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 8 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Test AX, AX + JZ MixModeCommon + Mov AX, 30 + Jmp MixModeCommon + +Mix6ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix6ModeSurround + + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Ch], AX ; Store into right volume + Mov BX, AX + ShL EAX, 16 + + Mov AL, 64 ; Do left volume + Sub AL, [SI+37h] ; AL = 64-FinalPan + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Eh], AX + + Mov ECX, EAX + + ; BX = right volume + ; CX = Left volume + Mov AX, 0 + Test ECX, ECX + JZ MixModeCommon + + Mov AL, 30 + Test BX, BX + JZ MixModeCommon + + Mov AL, 60 + Test CX, CX + JZ MixModeCommon + + Mov AL, 90 + Cmp CX, BX + JE MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix6ModeSurround: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 9 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + JZ MixModeCommon + Mov AX, 150 + Jmp MixModeCommon + +MixModeCommon: ; Requires AX = 30/60/90 etc. depending + ; On mixing mode type. + ; This will add 180 for 16-bit, + ; And sort out loop types. + Mov BL, [SI+0Ah] + Test Byte Ptr [SI+18h], 2 ; 16 bit? + JZ MixModeCommon1 + + Add AX, 180 + +MixModeCommon1: + Cmp BL, 8 + JB MixModeCommon3 ; No loop + JE MixModeCommon2 ; Forwards loop + + Add AX, 10 + +MixModeCommon2: + Add AX, 10 + +MixModeCommon3: + Add AX, Offset MixFunctionTables + Add AX, MixModeOffset + Mov [SI+8], AX ; Offset... + +MixSamplesMix: + Mov BX, [SI+8] ; BX = offset into + Mov EAX, [CS:BX+2] + Mov DWord Ptr PreMixFunction, EAX + Mov EAX, [CS:BX+6] + Mov DWord Ptr MixFunctionSeparateBackwards, EAX + + Mov AX, BytesToMix + Mov MixBlockSize, AX + Mov MixBufferOffset, MIXTABLESIZE + + Mov EAX, CURRENTPOSITION + Mov OLDPOSITION, EAX + + Call Word Ptr [CS:BX] + + And Word Ptr [SI], 0111100010001101b + Jmp MixSamplesEnd + +MixSamplesHandleError: + Mov Word Ptr [SI], 200h + + Test Byte Ptr [SI+3Ah], 80h + JNZ MixSamplesEnd + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Turn off channel + +MixSamplesEnd: + Pop CX + +MixSamplesEnd2: + Add SI, 128 + Dec CX + JNZ MixSamples2 + + Ret + +EndP MixSamples + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc CheckMIDI + + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Xor BX, BX + Call UARTIn + Mov BL, [MIDIBufferTail] + + Cmp AL, 0F0h + JAE CheckMIDIEnd + + Inc BL + Cmp BL, MIDIBufferHead + JE CheckMIDIEnd + + Mov [MIDIBuffer+BX], AL + Mov [MIDIBufferTail], BL + +CheckMIDIEnd: + Pop DS + Ret + +EndP CheckMIDI + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ESSIRQHandler + + PushAD + Push DS + Push ES + + ClD + + Mov AX, CS + Mov DS, AX + Assume DS:Driver + + Mov DX, [ConfigPort] + Add DL, 6 + In AL, DX + Test AL, 8 + JZ ESSNoMIDI + + Push AX + Call CheckMIDI + Pop AX + +ESSNoMIDI: + Test AL, 1 + JZ ESSIRQEnd + + Mov DX, [BasePort] + Add DL, 0Eh + In AL, DX + + Mov AX, MixBufferPos + Mov BX, AX + Mul DMASize + Cmp AX, DMABUFFERLENGTH + JB ESSIRQHandler2 + + Xor AX, AX + Xor BX, BX + +ESSIRQHandler2: + Inc BX + Mov MixBufferPos, BX + + CLD + + + ; OK... time to get next block + ; Check whether stereo thing is on.. + ; + LES DI, [ActualDMAPtr] + Add DI, AX + + Mov BX, DMASize ; BX = bytes required + ShR BX, 1 + ; BX = samples required + Mov BP, 8 ; Skip for mono + Mov CL, 14 ; Shift for mono + + Cmp Stereo, 0 + JE ESSIRQHandlerMono + + Mov BP, 4 ; Stereo skip value. + Dec CL + +ESSIRQHandlerMono: + Call SaveEMSPageFrame + + Cmp MixTransferRemaining, 0 + JNE ESSIRQHandler4 + Assume DS:Nothing + +ESSIRQHandler3: + Push BX + Push CX + Push BP + Push ES + Push DI + + Call Update + Call MixSamples + + Pop DI + Pop ES + Pop BP + Pop CX + Pop BX + +ESSIRQHandler4: + Mov DS, MixSegment + Mov SI, MixTransferOffset + Mov DX, BX ; DX = samples to transfer + Cmp DX, MixTransferRemaining + JBE ESSIRQHandler5 + + Mov DX, MixTransferRemaining + +ESSIRQHandler5: + Push DX + Cmp CS:Filter, 1 + JB ESSIRQHandler6 + JE ESSIRQHFilter + + Cmp CS:Stereo, 0 + JE ESSIRQ3QFilterMono + +ESSIRQ3QFilterStereo: + Push BX + + Mov EBX, FilterValue + Mov EBP, FilterValue2 + ShR DX, 1 + +ESSIRQ3QFilterStereo1: + Mov EAX, EBX + Mov ECX, EBP + Add EAX, [SI] + Add ECX, [SI+4] + SAR EAX, 1 + SAR ECX, 1 + Add EBX, EAX + Add EBP, ECX + SAR EBX, 1 + SAR EBP, 1 + + Mov EAX, EBX + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSS3QFilterStereoClip1 + Cmp EAX, 7FFFh + JG WSS3QFilterStereoClip2 + +ESSIRQ3QFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSS3QFilterStereoClip3 + Cmp EAX, 7FFFh + JG WSS3QFilterStereoClip4 + +ESSIRQ3QFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ ESSIRQ3QFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp WSSMixTransferEnd + +ESSIRQ3QFilterMono: + Push BX + + Mov EBX, FilterValue + +ESSIRQ3QFilterMono1: + Mov EAX, EBX + Add EAX, [SI] + SAR EAX, 1 + Add EBX, EAX + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL WSS3QFilterMonoClip1 + Cmp EAX, 7FFFh + JG WSS3QFilterMonoClip2 + +ESSIRQ3QFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ ESSIRQ3QFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp WSSMixTransferEnd + +ESSIRQHFilter: + Cmp CS:Stereo, 0 + JE ESSIRQHFilterMono + +ESSIRQHFilterStereo: + Push BX + + Mov EBX, FilterValue + Mov EBP, FilterValue2 + ShR DX, 1 + +ESSIRQHFilterStereo1: + Add EBX, [SI] + Add EBP, [SI+4] + + SAR EBX, 1 + SAR EBP, 1 + + Mov EAX, EBX + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSSHFilterStereoClip1 + Cmp EAX, 7FFFh + JG WSSHFilterStereoClip2 + +ESSIRQHFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSSHFilterStereoClip3 + Cmp EAX, 7FFFh + JG WSSHFilterStereoClip4 + +ESSIRQHFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ ESSIRQHFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp WSSMixTransferEnd + +ESSIRQHFilterMono: + Push BX + + Mov EBX, FilterValue + +ESSIRQHFilterMono1: + Add EBX, [SI] + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL WSSHFilterMonoClip1 + Cmp EAX, 7FFFh + JG WSSHFilterMonoClip2 + +ESSIRQHFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ ESSIRQHFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp WSSMixTransferEnd + +ESSIRQHandler6: + Mov EAX, [SI] + SAR EAX, CL + + Cmp EAX, -8000h + JL ESSIRQHandlerClip1 + Cmp EAX, 7FFFh + JG ESSIRQHandlerClip2 + +ESSIRQHandler7: + StosW ; } Memory write + + Add SI, BP + Dec DX + JNZ ESSIRQHandler6 + +WSSMixTransferEnd: + Pop DX + + Sub MixTransferRemaining, DX ; } Memory write + Sub BX, DX + JNZ ESSIRQHandler3 + + Mov MixTransferOffset, SI ; } Memory write + + Call RestoreEMSPageFrame + +ESSIRQEnd: + Mov AL, 20h + Cmp IRQ, 8 + JB WSSAckIRQ1 + + Out 0A0h, AL + +WSSAckIRQ1: + Out 20h, AL + + Pop ES + Pop DS + PopAD + IRet + +ESSIRQHandlerClip1: + Mov AX, 8000h + Jmp ESSIRQHandler7 + +ESSIRQHandlerClip2: + Mov AX, 7FFFh + Jmp ESSIRQHandler7 + +WSSHFilterMonoClip1: + Mov AX, 8000h + Jmp ESSIRQHFilterMono2 + +WSSHFilterMonoClip2: + Mov AX, 7FFFh + Jmp ESSIRQHFilterMono2 + +WSSHFilterStereoClip1: + Mov AX, 8000h + Jmp ESSIRQHFilterStereo2 + +WSSHFilterStereoClip2: + Mov AX, 7FFFh + Jmp ESSIRQHFilterStereo2 + +WSSHFilterStereoClip3: + Mov AX, 8000h + Jmp ESSIRQHFilterStereo3 + +WSSHFilterStereoClip4: + Mov AX, 7FFFh + Jmp ESSIRQHFilterStereo3 + +WSS3QFilterMonoClip1: + Mov AX, 8000h + Jmp ESSIRQ3QFilterMono2 + +WSS3QFilterMonoClip2: + Mov AX, 7FFFh + Jmp ESSIRQ3QFilterMono2 + +WSS3QFilterStereoClip1: + Mov AX, 8000h + Jmp ESSIRQ3QFilterStereo2 + +WSS3QFilterStereoClip2: + Mov AX, 7FFFh + Jmp ESSIRQ3QFilterStereo2 + +WSS3QFilterStereoClip3: + Mov AX, 8000h + Jmp ESSIRQ3QFilterStereo3 + +WSS3QFilterStereoClip4: + Mov AX, 7FFFh + Jmp ESSIRQ3QFilterStereo3 + +EndP ESSIRQHandler + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Add DI, Offset IRQData + Mov BX, [CS:DI] + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset ESSIRQHandler + + XChg [ES:BX], EAX + Mov OldESSIRQHandler, EAX + + Mov AX, IMR + And AX, [DI+2] + + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Pop ES + PopAD + + Ret + +EndP SetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Mov BX, [IRQData+DI] + + Mov EAX, OldESSIRQHandler + Mov [ES:BX], EAX + + Pop ES + PopAD + + Ret + +EndP ResetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetESSMixConst + + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, CmdLineMixSpeed + Mov CX, MixSpeed + Test AX, AX + JZ GetESSMixConst1 + + Mov CX, 22050 + Cmp AX, CX + JB GetESSMixConst1 + + Mov CX, 56821 + Cmp AX, CX + JA GetESSMixConst1 + + Mov CX, AX + +GetESSMixConst1: ; CX = mixspeed. + Mov DX, 0Ch + Mov AX, 236Ch ; DX:AX = 795.5kHz + Div CX + + Mov BX, AX + Neg AL + Mov ESSMixConst, AL + + Mov DX, 0Ch + Mov AX, 236Ch + Div BX + Mov MixSpeed, AX + + Pop DS + PopA + Ret + +EndP GetESSMixConst + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StartESS + + PushA + Push ES + Push DS + + Push CS + Pop DS + Assume DS:Driver + + ; Setup DMA + Mov BX, DMASegment + Xor AX, AX + Mov DX, DMA + Mov DI, DMABUFFERLENGTH + Call SetDMA + + LES DI, ActualDMAPtr + Xor AX, AX + Mov CX, DMABUFFERLENGTH/2 + Rep StosW + + Mov MixBufferPos, 0 + Mov MixTransferRemaining, 0 + + Call ResetDSP + Mov DX, BasePort + Add DL, 0Ch + +; Extended Functions + + Mov AL, 0C6h + Call ESSOut + +; Autoinit DMA + + Mov AL, 0B8h + Call ESSOut + Mov AL, 4 + Call ESSOut + +; Stereo/Mono select + + Mov AH, 0A8h + Call ESSReadRegister + Mov AH, AL + Mov AL, 0A8h + Call ESSOut + Mov AL, AH + And AL, Not 3 + Or AL, 2 + Cmp Stereo, 0 + JE StartESS1 + + Xor AL, 3 + +StartESS1: + Call ESSOut + +; DMA mode + + Mov AL, 0B9h + Call ESSOut + Mov AL, 2 + Call ESSOut + +; Mixspeed + + Mov AL, 0A1h + Call ESSOut + Mov AL, ESSMixConst + Call ESSOut + +; Filter clock divider + Mov AL, 0A2h + Call ESSOut + + Mov AL, 0FEh + Call ESSOut + +; DMA counter + Mov CX, DMASize + Neg CX + + Mov AL, 0A4h + Call ESSOut + Mov AL, CL + Call ESSOut + Mov AL, 0A5h + Call ESSOut + Mov AL, CH + Call ESSOut + +; Initialise DAC + Mov AL, 0B6h + Call ESSOut + Mov AL, 0 + Call ESSOut + +; Configure DACs + + Mov AL, 0B7h + Call ESSOut + Mov AL, 71h + Call ESSOut + + Mov AL, 0B7h + Call ESSOut + + Mov AL, 0BCh + Cmp Stereo, 0 + JNE StartESS2 + + Mov AL, 0F4h + +StartESS2: + Call ESSOut + +; IRQ configuration + Mov AL, 0B1h + Call ESSOut + Mov AL, 50h + Call ESSOut + +; DMA configuration + Mov AL, 0B2h + Call ESSOut + Mov AL, 50h + Call ESSOut + +; Enable voice + Mov AL, 0D1h + Call ESSOut + +; Start transfer + Mov AH, 0B8h + Call ESSReadRegister + Mov AH, AL + Mov AL, 0B8h + Call ESSOut + Mov AL, AH + Or AL, 1 + Call ESSOut + +; Init UART + Mov DX, MIDIPort + Inc DX + Mov AL, 3Fh ; Intelligent mode. + Out DX, AL + +; Enable MIDI IRQ + Mov DX, BasePort + Add DL, 4 + Mov AX, 4064h + Out DX, AX + + Pop DS + Pop ES + PopA + + Ret + +EndP StartESS + Assume DS:Nothing + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov SI, Offset RelocationTable + +RelocationFix: + LodsW + Test AX, AX + JZ RelocationEnd + Mov BX, AX + Mov [BX], DS + Jmp RelocationFix + + +RelocationEnd: + Call GetEMSPageFrame + Mov EMSPageFrame, AX + + In AL, 0A1h + Mov AH, AL + In AL, 21h + Mov IMR, AX + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + Mov DX, BasePort + Add DL, 4 + Mov AL, 22h + Out DX, AL + Inc DX + In AL, DX + Mov AH, AL + And AX, 0FF0h + ShR AH, 1 + ShR AL, 5 + Mov Word Ptr [VolumeTable], AX + + Call GetESSMixConst + + Mov AX, 2643 + Mul MixSpeed + Add AX, 0FFFFh + AdC DX, 2080 + + Mov BX, (DMABUFFERLENGTH*2)/16 + Add BX, DX + + ; Allocate MixSegment first + Mov AH, 48h + + Int 21h + JNC InitSound1 + +InitSoundNoMemory: + Mov SI, Offset ESSNoMemoryMsg + Ret + +InitSound1: + Mov MixSegment, AX + Add AX, DX + Mov DMASegment, AX + + Call SetIRQ + Call GetTempo + Call SetTempo + + Mov SI, Offset ESSMsg + + Mov AX, BasePort + Mov BX, IRQ + Mov CX, DMA + + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Call ResetIRQ + Call SetIRQ + + Mov SI, Offset ReInitMsg + Mov BX, 40 + Call SetInfoLine + + Mov AL, Stereo + Call SetStereo + + Pop ES + Pop DS + PopA + + Ret + +EndP ReInitSound + Assume DS:Nothing + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, IMR + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Mov AX, MixSegment + Test AX, AX + JZ UnInitSound1 + + Mov ES, AX + Mov AH, 49h ; Release MixSegment + Int 21h + + Call ResetDSP + Call ResetIRQ + +UnInitSound1: + Ret + +EndP UnInitSound + Assume DS:Nothing + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + Push CS + Pop DS + Assume DS:Driver + +Poll1: + Call [UARTBufferEmpty] + JNC PollEnd + + Xor BX, BX + + ClI + + Mov BL, MIDIBufferHead + Cmp BL, MIDIBufferTail + JZ PollEnd ; Nothing in queue + + Inc BL + Mov AL, [MIDIBuffer+BX] + Mov MIDIBufferHead, BL + + Call [UARTSend] + Jmp Poll1 + +PollEnd: + StI + + Ret + +EndP Poll + Assume DS:Nothing + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Push AX + Push BX + Push DX + + Push BX + + Mov AX, MixSpeed + Mov BX, AX + Xor DX, DX + + ShL AX, 1 + RCL DX, 1 ; DX:AX = Mixspeed*2 + + ShR BX, 1 ; BX = Mixspeed/2 + + Add AX, BX + AdC DX, 0 ; DX:AX = Mixspeed*2.5 + + Pop BX ; BX = tempo + Div BX + + Mov BytesToMix, AX + + Pop DX + Pop BX + Pop AX + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + PushA + Push DS + + Mov BX, AX ; BX = MixVolume + Mov CS:MixVolume, BX + + Mov AX, CS:MixSegment + Test AX, AX + JZ SetMixVolume2 + + Mov DS, AX + + Mov CX, MIXTABLESIZE/2 + Mov SI, MIXTABLESIZE-2; Starting point - working backwards + +SetMixVolume1: + Mov AX, CX + + Dec AX ; AH = volume, AL = wave value. + Xor DX, DX + XChg AH, DL ; DL = Volume, AX = wave value + CBW + + IMul DX ; DX:AX = Volume * Wave Value + ; Ranges -8192->8128 + + IMul BX ; DX:AX = Volume * Wave Value * Mixing Volume + ; Ranges -1048576->1040384 + + Add AX, 64 + AdC DX, 0 + + ShRD AX, DX, 7 + Mov [SI], AX + Sub SI, 2 + + Loop SetMixVolume1 + +SetMixVolume2: + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS:RecalculateAllVolumes + + Pop DS + PopA + + Ret + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Mov CS:Stereo, AL + Cmp CS:MixSegment, 0 + JE SetStereo1 + + Call ResetDSP + Call StartESS + +SetStereo1: + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include loadsam.inc + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset ESSScreenList + + ClC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far + + Xor AH, AH + Mov AL, [CS:VolumeTable+DI] + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far + + Push DS + Push DX + + Push CS + Pop DS + Assume DS:Driver + + Mov [VolumeTable+DI], AL + + Mov DX, BasePort + Add DL, 4 + Mov AL, 22h + Out DX, AL + Mov AH, [VolumeTable] + ShL AH, 4 + Or AH, [VolumeTable+1] + ShL AH, 1 + Out DX, AX + + Pop DX + Pop DS + Ret + +EndP SetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. + +StopAfterPlay DW 0 +DefaultChannels DW 64 + DW 5 Dup (0) + + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/GUS.INC b/SoundDrivers/GUS.INC new file mode 100755 index 0000000..4770d30 --- /dev/null +++ b/SoundDrivers/GUS.INC @@ -0,0 +1,2316 @@ + + .386P + Jumps + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +;************************** + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;************** Local variables **************** + +SLAVECHANNELSIZE EQU 128 + +GUSReinitMsg DB "Gravis UltraSound reinitialised", 0 + +GUSID DB "Gravis UltraSound detected", 13 + DB "Port ", 0FDh, "Xh, ", 0FDh, "Dk Memory", 0 + +GUSID2 DB "Gravis UltraSound detected", 13 + DB "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, ", 0FDh, "Dk RAM", 0 + +GUSFreeMsg DB "FreeGUS ", 0FDh, "Dk", 0 + +IFDEF RIC + +GUSFreeMsg2 DB "FreeGUS ", 0FDh, "Dk", 13, 13 + DB "GUSInit ", 0FDh, "D", 0 + + IFDEF RAMP + DriverName DB "ITGUS.DRV", 0 + ELSE + DriverName DB "ITGUS2.DRV", 0 + ENDIF + +ENDIF + +ULTRASndString DB "ULTRASND" + +GUSMixTable Label Word + + DW 44100, 41160, 38588, 36318, 34300, 32495, 30870, 29400, 28064 + DW 26844, 25725, 24696, 23746, 22867, 22050, 21290, 20580, 19916 + DW 19294 + +GUSVolumeTable Label Word + DW 04000h, 07FF0h, 08FF0h, 09800h, 09FF0h, 0A400h, 0A800h, 0AC00h + DW 0AFF0h, 0B200h, 0B400h, 0B600h, 0B800h, 0BA00h, 0BC00h, 0BE00h + DW 0BFF0h, 0C100h, 0C200h, 0C300h, 0C400h, 0C500h, 0C600h, 0C700h + DW 0C800h, 0C900h, 0CA00h, 0CB00h, 0CC00h, 0CD00h, 0CE00h, 0CF00h + + DW 0CFF0h, 0D080h, 0D100h, 0D180h, 0D200h, 0D280h, 0D300h, 0D380h + DW 0D400h, 0D480h, 0D500h, 0D580h, 0D600h, 0D680h, 0D700h, 0D780h + DW 0D800h, 0D880h, 0D900h, 0D980h, 0DA00h, 0DA80h, 0DB00h, 0DB80h + DW 0DC00h, 0DC80h, 0DD00h, 0DD80h, 0DE00h, 0DE80h, 0DF00h, 0DF80h + + DW 0DFF0h, 0E040h, 0E080h, 0E0C0h, 0E100h, 0E140h, 0E180h, 0E1C0h + DW 0E200h, 0E240h, 0E280h, 0E2C0h, 0E300h, 0E340h, 0E380h, 0E3C0h + DW 0E400h, 0E440h, 0E480h, 0E4C0h, 0E500h, 0E540h, 0E580h, 0E5C0h + DW 0E600h, 0E640h, 0E680h, 0E6C0h, 0E700h, 0E740h, 0E780h, 0E7C0h + + DW 0E800h, 0E840h, 0E880h, 0E8C0h, 0E900h, 0E940h, 0E980h, 0E9C0h + DW 0EA00h, 0EA40h, 0EA80h, 0EAC0h, 0EB00h, 0EB40h, 0EB80h, 0EBC0h + DW 0EC00h, 0EC40h, 0EC80h, 0ECC0h, 0ED00h, 0ED40h, 0ED80h, 0EDC0h + DW 0EE00h, 0EE40h, 0EE80h, 0EEC0h, 0EF00h, 0EF40h, 0EF80h, 0EFC0h + + DW 0EFF0h + +ALIGN 4 + +GUSDataTable DD 100 Dup (0FFFFFFFFh) +GUSMemory DW 0 ; kb of memory on GUS +GUSRegisterSelect DW 0 +GUSVoiceSelect DW 0 +GUSUpdateTimer DW 0 +GUSUpdateCount DW 0 +GUSMemoryFree DD 0 +MixSpeed DW 0 +OldIRQHandler DD 0 + +CONFIGURATIONOFFSET EQU $+128 +CONFIGSIZE EQU 8 + +Convert16To8Bit DB 0 + DB 0 +Compress DB 0 + DB 0 + +IFDEF RIC + ShowReinit DB 0 + DB 0 + UsedChannels DW ? +ENDIF + +Stereo DB 0 +GUSUpdateFlag DB 0 + +MIDIIRQ DW 0FFFFh +MIDIBuffer DB 256 Dup (0) +MIDIBufferHead DB 0 +MIDIBufferTail DB 0 +MIDIOldIRQHandler DD 0 + +IRQData Label Word + DW 20h, 1111111111111110b ; IRQ 0 + DW 24h, 1111111111111101b ; IRQ 1 + DW 28h, 1111110111111011b ; IRQ 2 + DW 2Ch, 1111111111110111b ; IRQ 3 + DW 30h, 1111111111101111b ; IRQ 4 + DW 34h, 1111111111011111b ; IRQ 5 + DW 38h, 1111111110111111b ; IRQ 6 + DW 3Ch, 1111111101111111b ; IRQ 7 + DW 1C0h, 1111111011111011b ; IRQ 8 + DW 1C4h, 1111110111111011b ; IRQ 9 + DW 1C8h, 1111101111111011b ; IRQ 10 + DW 1CCh, 1111011111111011b ; IRQ 11 + DW 1D0h, 1110111111111011b ; IRQ 12 + DW 1D4h, 1101111111111011b ; IRQ 13 + DW 1D8h, 1011111111111011b ; IRQ 14 + DW 1DCh, 0111111111111011b ; IRQ 15 + +IMR DW 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +GUSScreenList Label + DW 6 + DW Near Ptr IdleFunctionList + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr GravisHeaderLine + + DW SampleText ; 4 + + DW ConvertSampleText + DW ConvertDisabledButton ; 6 + DW ConvertEnabledButton + + DW SampleSizeText ; 8 + DW SampleSize0Button ; 9 + DW SampleSize1Button + DW SampleSize2Button + + +IFDEF RIC + DW ReinitText ; 12 + DW ReinitButton0 + DW ReinitButton1 + DW ReinitButton2 + +ENDIF + + DW DriverText + + DW 0 + +GravisHeaderLine DW 10 + DB "Gravis UltraSound Driver", 0 + +DriverText DW 1 + DB 30, 48 + DB 21h + DB "Gravis UltraSound Driver 1.3 for Impulse Tracker", 0 + +SampleText DW 1 + DB 3, 13 + DB 20h + DB "Sample resizing options", 0 + +ConvertSampleText DW 1 + DB 5, 15 + DB 20h + DB "Reduce 16 bit samples to 8 bit", 0 + +ConvertDisabledButton DW 2 + DW 0FFFFh, 7, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetConvert +DriverSegment1 DW 0 + DW 0 + DW Offset SetConvert +DriverSegment2 DW 0 + DB 7, 17, 20, 19, 8 + DB 0 + DB " Disabled", 0 + +ConvertEnabledButton DW 2 + DW 6, 9, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetConvert +DriverSegment3 DW 0 + DW 1 + DW Offset SetConvert +DriverSegment4 DW 0 + DB 7, 20, 20, 22, 8 + DB 0 + DB " Enabled", 0 + +SampleSizeText DW 1 + DB 5, 24 + DB 20h + DB "Sample size", 0 + +SampleSize0Button DW 2 + DW 7, 10, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetCompress +DriverSegment5 DW 0 + DW 0 + DW Offset SetCompress +DriverSegment6 DW 0 + DB 7, 26, 20, 28, 8 + DB 0 + DB " Original", 0 + +SampleSize1Button DW 2 + DW 9, 11, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetCompress +DriverSegment7 DW 0 + DW 1 + DW Offset SetCompress +DriverSegment8 DW 0 + DB 7, 29, 20, 31, 8 + DB 0 + DB " Half", 0 + +IFDEF RIC + + SampleSize2Button DW 2 + DW 10, 13, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetCompress + DriverSegment9 DW 0 + DW 2 + DW Offset SetCompress + DriverSegment10 DW 0 + DB 7, 32, 20, 34, 8 + DB 0 + DB " Quarter", 0 + + ReinitText DW 1 + DB 3, 36 + DB 20h + DB "Show channel reinitialisation", 0 + + ReinitButton0 DW 2 + DW 11, 14, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetReinit + DriverSegment11 DW 0 + DW 0 + DW Offset SetReinit + DriverSegment12 DW 0 + DB 7, 38, 21, 40, 8 + DB 0 + DB " Disabled", 0 + + ReinitButton1 DW 2 + DW 13, 15, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetReinit + DriverSegment13 DW 0 + DW 1 + DW Offset SetReinit + DriverSegment14 DW 0 + DB 7, 41, 21, 43, 8 + DB 0 + DB " Channels", 0 + + ReinitButton2 DW 2 + DW 14, 0FFFFh, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetReinit + DriverSegment15 DW 0 + DW 2 + DW Offset SetReinit + DriverSegment16 DW 0 + DB 7, 44, 21, 46, 8 + DB 0 + DB " Frequency", 0 + +ELSE + + SampleSize2Button DW 2 + DW 10, 0FFFFh, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetCompress + DriverSegment9 DW 0 + DW 2 + DW Offset SetCompress + DriverSegment10 DW 0 + DB 7, 32, 20, 34, 8 + DB 0 + DB " Quarter", 0 + + +ENDIF + + +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +IdleFunctionList DD 0 + DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +RelocationTable Label + DW Offset DriverSegment1, Offset DriverSegment2 + DW Offset DriverSegment3, Offset DriverSegment4 + DW Offset DriverSegment5, Offset DriverSegment6 + DW Offset DriverSegment7, Offset DriverSegment8 + DW Offset DriverSegment9, Offset DriverSegment10 + +IFDEF RIC + DW Offset DriverSegment11, Offset DriverSegment12 + DW Offset DriverSegment13, Offset DriverSegment14 + DW Offset DriverSegment15, Offset DriverSegment16 +ENDIF + DW 0FFFFh + +;*********** Local functions ******************* +; +; GUSDelay - produces delay between GUS commands +; TestGUS - Checks for the presence of a GUS by detecting amount of memory. +; LoadGUSSample - Loads a byte to GUS, EDI = position in memory, AL = value +; LoadGUSSamples - Loads ECX bytes from DS:SI to EDI +; +;*********************************************** + +Proc GUSDelay + + Push AX + Push DX + + Mov DX, 300h + + In AL, DX + In AL, DX + In AL, DX + In AL, DX + In AL, DX + In AL, DX + In AL, DX + In AL, DX + + Pop DX + Pop AX + + Ret + +EndP GUSDelay + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetGUS ; AX = baseport. + + Push AX + Push DX + + Mov DX, AX + Add DX, 103h ; Select register + + Mov AL, 4Ch ; Reset global register + Out DX, AL + + Add DL, 2 ; 8 bit data + Xor AL, AL + Out DX, AL ; Reset GUS! + + Call GUSDelay + Call GUSDelay + + Mov AL, 1 + Out DX, AL + + Call GUSDelay + Call GUSDelay + + Pop DX + Pop AX + + Ret + +EndP ResetGUS + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc TestGUS + + Push AX + + Call ResetGUS + + Mov GUSMemory, 0 + + Mov DX, AX + Add DX, 103h ; DX = Select Register + + Mov CX, 4 ; Max amount is 1MB of memory + Xor BL, BL ; Start with first 256k pool + +TestGUS1: + Mov AL, 44h ; GUS DRAM High, 8 bit + Out DX, AL + + Add DL, 2 + Mov AL, BL + Out DX, AL + + Sub DL, 2 ; DX = Select Register + + Mov AL, 43h ; GUS DRAM Low, 16 bit + Out DX, AL + + Inc DX ; DX = Baseport+104h + Xor AX, AX + Out DX, AX ; Address 0 + + Add DL, 3 ; DX = Baseport+107h (DRAM I/O) + Mov AL, 55h + Out DX, AL ; Write value 055h + + Sub DL, 3 ; DX = Baseport+104h + Mov AX, 1 + Out DX, AX ; Address 1 + + Add DL, 3 ; DX = Baseport+107h + Mov AL, 0AAh + Out DX, AL ; Write value 0AAh + + Sub DL, 3 ; DX = Baseport+104h + Mov AX, 2 + Out DX, AX ; Address 2 + + Add DL, 3 ; DX = Baseport+107h + Mov AL, 0 + Out DX, AL ; Write value + + Sub DL, 3 ; DX = Baseport+104h + Xor AX, AX + Out DX, AX ; Address 0 + + Add DL, 3 ; DX = Baseport+107h + In AL, DX ; Read value.. should be 055h + Cmp AL, 55h + JNE TestGUS2 + + Sub DL, 3 ; DX = Baseport+104h + Mov AX, 1 + Out DX, AX ; Address 1 + + Add DL, 3 ; DX = Baseport+107h + In AL, DX ; Read value.. should be 0AAh + Cmp AL, 0AAh + JNE TestGUS2 + + Sub DL, 3 ; DX = Baseport+104h + Mov AX, 2 + Out DX, AX ; Address 2 + + Add DL, 3 ; DX = Baseport+107h + In AL, DX ; Read value.. + Cmp AL, 0 + JNE TestGUS2 + + Sub DL, 4 ; DX = Baseport+103h + + Add GUSMemory, 256 ; Another 256k! + + Add BL, 4 ; Next memory chunk + Loop TestGUS1 + + +TestGUS2: + Pop AX + + Cmp GUSMemory, 0 + JNE TestGUS3 + + StC + Ret + +TestGUS3: + ClC + Ret + +EndP TestGUS + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc LoadGUSSample ; EDI = position, AL = value + + Push EAX + + Mov DX, CS:GUSRegisterSelect + Mov AL, 44h + Out DX, AL + + Add DL, 2 + Mov EAX, EDI + ShR EAX, 16 + Out DX, AL + Sub DL, 2 ; Select register again. + + Mov AL, 43h ; Address Low, 16 bit + Out DX, AL + Inc DX ; DX = 3x4h + + Mov AX, DI ; Memory location high + Out DX, AX ; Memory location done. + + Add DL, 3 + + Pop EAX + + Out DX, AL + Sub DL, 3 + + Inc EDI + + Ret + +EndP LoadGUSSample + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc LoadGUSSamples ; Given DS:SI, EDI = pos, ECX = count + ; EBP = step value. + +LoadGUSSamples1: + Mov DX, CS:GUSRegisterSelect + Mov AL, 44h + Out DX, AL + + Add DL, 2 + Mov EAX, EDI + ShR EAX, 16 + Out DX, AL + Sub DL, 2 ; Select register again. + + Mov AL, 43h ; Address Low, 16 bit + Out DX, AL + Inc DX ; DX = 3x4h + +LoadGUSSamples2: + Mov AX, DI ; Memory location high + Out DX, AX ; Memory location done. + + Add DL, 3 + + Mov AL, [SI] + Add SI, BP + JC LoadGUSSamples4 + +LoadGUSSamples3: + Out DX, AL + Sub DL, 3 + + Inc DI + JZ LoadGUSSamples5 + + Dec ECX + JNZ LoadGUSSamples2 + Ret + +LoadGUSSamples4: + Add ESI, 10000h + Call UpdateSampleLocation + Jmp LoadGUSSamples3 + +LoadGUSSamples5: + Add EDI, 10000h + LoopD LoadGUSSamples1 + Ret + +EndP LoadGUSSamples + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Load16GUSSamples ; Given DS:SI, EDI = pos, ECX = count + ; EBP = step value. + + Add BP, BP + Dec BP + Mov BX, 1 + Xor BP, BX + Xor BX, BP + +Load16GUSSamples1: + Mov DX, CS:GUSRegisterSelect + Mov AL, 44h + Out DX, AL + + Add DL, 2 + Mov EAX, EDI + ShR EAX, 16 + Out DX, AL + Sub DL, 2 ; Select register again. + + Mov AL, 43h ; Address Low, 16 bit + Out DX, AL + Inc DX ; DX = 3x4h + +Load16GUSSamples2: + Mov AX, DI ; Memory location high + Out DX, AX ; Memory location done. + + Add DL, 3 + + Xor BX, BP + Mov AL, [SI] + Add SI, BX + JC Load16GUSSamples4 + +Load16GUSSamples3: + Out DX, AL + Sub DL, 3 + + Inc DI + JZ Load16GUSSamples5 + + LoopD Load16GUSSamples2 + Ret + +Load16GUSSamples4: + Add ESI, 10000h + Call UpdateSampleLocation + Jmp Load16GUSSamples3 + +Load16GUSSamples5: + Add EDI, 10000h + LoopD Load16GUSSamples1 + Ret + +EndP Load16GUSSamples + +;*********** Public functions ****************** + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectGUS Far + + Push CS + Pop DS + Assume DS:Driver + + Cmp BasePort, 0FFFFh + JE DetectGUS1 + + Mov AX, BasePort + + Cmp AX, 210h + JB DetectCardError + Cmp AX, 280h + JA DetectCardError + + Call TestGUS + JNC DetectGUS3 + Jmp DetectCardError + +DetectGUS1: + Mov AX, 210h + +DetectGUS2: + Call TestGUS + JNC DetectGUS3 + + Add AL, 10h + Cmp AL, 60h + JBE DetectGUS2 + +DetectCardError: + StC + Ret + +DetectGUS3: + Mov BasePort, AX + Add AX, 102h + Mov GUSVoiceSelect, AX + Inc AX + Mov GUSRegisterSelect, AX + +Comment ~ + + ; If Windows *AND* IRQ = 0FFFFh, then grab from ULTRASND variable + + Mov SI, Offset ULTRASNDString + Mov CX, 8 + Call GetEnvironment ; Returns ES:DI, Carry if error + JC DetectCardOK + + Mov CX, 3 ; Find 3 commas first. + ; Eg. skip baseport + 2 DMAs + +DetectCard1: + Mov AL, [ES:DI] + Inc DI + + Cmp AL, ',' + JNE DetectCard1 + Loop DetectCard1 + + ; GUS IRQ.. + Xor DX, DX + +DetectCardIRQ1_1: + Mov AL, [ES:DI] + Inc DI + Cmp AL, ',' + JE DetectCardIRQ1_2 + + Sub AL, '0' + JC DetectCardError + Cmp AL, 9 + JA DetectCardError + + IMul DX, 10 + Add DL, AL + Jmp DetectCardIRQ1_1 + +DetectCardIRQ1_2: ; DX = IRQ to use. + Cmp DX, 15 + JA DetectCardError + + Mov AX, 1600h + Int 2Fh ; Windows Detect. + + Test AL, 7Fh + JZ DetectCardIRQ2_1 + + Mov AX, IRQ + Cmp AX, -1 + JNE DetectCardIRQ2_2 + Mov IRQ, DX + Mov MIDIIRQ, DX + Jmp DetectCardOK + +DetectCardIRQ2_2: + Mov DX, AX + +DetectCardIRQ2_1: ; No Windows. + Mov MIDIIRQ, DX + +DetectCardOK: + +~ + + Mov EAX, 'Jeff' + ClC + Ret + +EndP DetectGUS + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GUSIRQHandler ; IRQ Handler has to + ; 1) Update GUS registers + ; 2) Update song position + Push AX + Push DS + + Mov AX, GUSUpdateTimer + Add GUSUpdateCount, AX + JC GUSIRQHandler1 + + Mov AL, 20h + Out 20h, AL + Jmp GUSIRQHandler2 + +GUSIRQHandler1: + PushF + Call [OldIRQHandler] + +GUSIRQHandler2: + Xor GUSUpdateFlag, 1 + JZ GUSIRQHandlerEnd + + PushAD + Push ES + + ClD + + Call SaveEMSPageFrame + Call Update ; Returns DS:SI, CX + Call SetGUSRegisters + Call RestoreEMSPageFrame + + Pop ES + PopAD + +GUSIRQHandlerEnd: + Pop DS + Pop AX + IRet + +EndP GUSIRQHandler + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Comment ~ + +Proc CheckMIDI + + Push AX BX DX DS + + Push CS + Pop DS + Assume DS:Driver + + Mov DX, BasePort + Inc DH + +CheckMIDIAgain: + In AL, DX + Test AL, 1 + JZ CheckMIDI1 + + Inc DX + In AL, DX + Dec DX + + Cmp AL, 0F0h +; JAE CheckMIDIAgain + JAE CheckMIDI1 + + Mov BL, [MIDIBufferTail] + Inc BL + Cmp BL, [MIDIBufferHead] + JE CheckMIDI1 +; JE CheckMIDIAgain + + Mov [MIDIBuffer+BX], AL + Mov [MIDIBufferTail], BL +; Jmp CheckMIDIAgain + +CheckMIDI1: + Pop DS DX BX AX + Ret + +EndP CheckMIDI + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GUSMIDIIRQHandler + + Push AX BX DX DS + + Push CS + Pop DS + Assume DS:Driver + + Call CheckMIDI + + Mov AL, 20h + + Cmp MIDIIRQ, 8 + JB GUSMIDIIRQHandler1 + + Out 0A0h, AL + +GUSMIDIIRQHandler1: + Out 20h, AL + + Pop DS DX BX AX + IRet + +EndP GUSMIDIIRQHandler + Assume DS:Nothing + +~ + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GUSIRQOnlyHandler + + PushAD + Push DS + Push ES + + Mov AL, 20h + + Cmp CS:IRQ, 8 + JB GUSIRQOnlyHandler1 + + Out 0A0h, AL + +GUSIRQOnlyHandler1: + Out 20h, AL + +GUSIRQAgain: + Mov DX, CS:BasePort + Add DL, 6 + In AL, DX + +; Test AL, 2 ; MIDI receive? +; JZ GUSIRQOnlyHandlerNoMIDI +; +; Call CheckMIDI +; +; Jmp GUSIRQAgain + +GUSIRQOnlyHandlerNoMIDI: + Test AL, 8 + JZ GUSIRQOnlyHandler3 + + Mov DX, CS:GUSRegisterSelect + Mov AL, 45h + Out DX, AL + Mov AL, 0 + Add DL, 2 + Out DX, AL + Mov AL, 8 + Out DX, AL + Sub DL, 2 + + CLD + + Call SaveEMSPageFrame + Call Update + Call SetGUSRegisters + Call RestoreEMSPageFrame + Jmp GUSIRQAgain + +GUSIRQOnlyHandler3: + Test AL, 60h + JZ GUSIRQOnlyHandler2 + + Mov DX, CS:GUSVoiceSelect + In AL, DX + Push AX + +GUSIRQOnlyHandler4: + Mov DX, CS:GUSRegisterSelect + Mov AL, 8Fh + Out DX, AL + Add DL, 2 + In AL, DX ; Bit 6 = waveramp IRQ + ; Bit 7 = wavetable IRQ... + ; Bit 0-5 = voice + + Test AL, 080h + JZ GUSIRQOnlyHandler5 + Test AL, 040h + JZ GUSIRQOnlyHandler6 + + Pop AX + Mov DX, CS:GUSVoiceSelect + Out DX, AL + +; Jmp GUSIRQAgain + Jmp GUSIRQOnlyHandler2 + +GUSIRQOnlyHandler5: ; Wavetable IRQ + Push AX + Mov DX, CS:GUSVoiceSelect + And AL, 31 + Out DX, AL + Call GUSDelay + + Inc DX + + Xor AL, AL + Out DX, AL ; AL = 0 (Mode control) + Mov AL, 2 + Add DL, 2 + Out DX, AL + Call GUSDelay + Out DX, AL + + Pop AX + Test AL, 40h + JNZ GUSIRQOnlyHandler4 + +GUSIRQOnlyHandler6: ; Volume IRQ + Mov DX, CS:GUSVoiceSelect + And AL, 31 + Out DX, AL + Call GUSDelay + + Inc DX + Mov AL, 0Dh ; Volume Ramp. + Out DX, AL + + Mov AL, 3 + Add DL, 2 + Out DX, AL + Sub DL, 2 + + Mov AL, 6 ; Ramp rate + Out DX, AL + + Mov AL, 63 ; Ramp rate + Add DL, 2 + Out DX, AL + Sub DL, 2 + + Jmp GUSIRQOnlyHandler4 + + +GUSIRQOnlyHandler2: + Pop ES + Pop DS + PopAD + + IRet + +EndP GUSIRQOnlyHandler + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +IFDEF RAMP + include gusramp.inc +ELSE + include gusnramp.inc +ENDIF + +IFDEF RIC + include gusric.inc +ELSE + include gusnric.inc +ENDIF + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GUSGetAddress ; Given EAX + Assume DS:Nothing + + Push CX + + Mov CL, CS:Compress + ShR EAX, CL + + Pop CX + Add EAX, [CS:GUSDataTable+BX] + ShL EAX, 9 + + Ret + +EndP GUSGetAddress + +;ÄÄ InitMIDIIRQ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Comment ~ + +Proc InitMIDIIRQ + + Ret + + + PushA + Push DS + Push ES + + Mov AX, CS + Mov DS, AX + ShL EAX, 16 + Mov ES, AX + Assume DS:Driver + + Mov BX, MIDIIRQ + Cmp BX, 15 + JA InitMIDIIRQ1 + + ShL BX, 2 + Mov SI, [IRQData+BX] + + Mov AX, Offset GUSMIDIIRQHandler + XChg [ES:SI], EAX + + Mov MIDIOldIRQHandler, EAX + + In AL, 0A1h + Mov AH, AL + In AL, 21h + + And AX, [IRQData+BX+2] ; Update mask + + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Mov DX, BasePort + Inc DH + Mov AL, 0FFh + Out DX, AL + Mov AL, 0FCh + Out DX, AL + Jmp InitMIDIIRQEnd + +InitMIDIIRQ1: + Mov DX, BasePort + Inc DH + Mov AL, 0FFh + Out DX, AL + Mov AL, 0h + Out DX, AL + +InitMIDIIRQEnd: + Pop ES + Pop DS + PopA + + Ret + +EndP InitMIDIIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitMIDIIRQ + + Ret + + PushA + Push DS + Push ES + + Mov BX, MIDIIRQ + Cmp BX, 15 + JA UnInitMIDIIRQ1 + + ShL BX, 2 + Mov BX, [IRQData+BX] + Xor AX, AX + Mov ES, AX + + Mov EAX, MIDIOldIRQHandler + Mov [ES:BX], EAX + +UnInitMIDIIRQ1: + Mov DX, Baseport + Inc DH + Mov AL, 0FFh + Out DX, AL + + Pop ES + Pop DS + PopA + + Ret + +EndP UnInitMIDIIRQ + Assume DS:Nothing + +~ + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + Mov SI, Offset RelocationTable + +RelocationSetup: + Mov BX, [SI] + Cmp BX, 0FFFFh + JE RelocationSetupFinished + + Mov [BX], CS + + Add SI, 2 + Jmp RelocationSetup + +RelocationSetupFinished: + ; OK... disable the GUS Line In + ; & Enable Line Out + Mov BX, AX + + Mov DX, BasePort + Mov AL, 1 + Out DX, AL + + Call ResetGUS + + Cmp BL, 14 + JAE InitSound_GUS4 + + Mov BL, 14 + +InitSound_GUS4: + +IFDEF RIC + Mov UsedChannels, BX +ENDIF + + Mov DX, GUSRegisterSelect ; Tell the GUS how many voices + Mov AL, 0Eh ; to use + Out DX, AL + + Add DL, 2 ; DX = BasePort + 105h + Mov AL, BL + Dec AL + Or AL, 0C0h + Out DX, AL ; Number of Voices set + + ; Reset each voice + Mov CX, 32 ; 32 voices to clear. + + Sub BX, 14 ; Now get mixspeed + Add BX, BX + Mov AX, [GUSMixTable+BX] + Mov MixSpeed, AX + + Sub DL, 3 ; DX = Voice select register + +GUSResetVoice: + Mov AL, CL + Dec AL + Out DX, AL + + Inc DX ; DX = BasePort + 103h + Xor AL, AL ; Voice control register, 8 bit + Out DX, AL + + + Add DL, 2 + Mov AL, 2 + Out DX, AL ; Stop voice + Sub DL, 2 + + Mov AL, 0Dh ; Volume Ramp. + Out DX, AL + + Mov AL, 3 + Add DL, 2 + Out DX, AL + Call GUSDelay + Out DX, AL + Sub DL, 2 + + Mov AL, 6 ; Ramp rate + Out DX, AL + + Mov AL, 63 ; Ramp rate + Add DL, 2 + Out DX, AL + Sub DL, 2 + + Mov AL, 9 ; Volume register, 16 bit + Out DX, AL + + Inc DX + Xor AX, AX + Out DX, AX ; No volume + Call GUSDelay + Out DX, AX + + ClI + Sub DL, 2 ; DX = BasePort + 102h = Voice select. + + Loop GUSResetVoice + + In AL, 0A1h + Mov AH, AL + In AL, 21h + Mov IMR, AX + +; Call InitMIDIIRQ + + Cmp IRQ, 0FFFFh + JE InitSound_GUS1 + + Mov AX, BasePort + Call ResetGUS + + ; Set IRQ + Mov BX, IRQ + ShL BX, 2 ; BX points to offset in IRQData + + Xor DI, DI + Mov ES, DI + Mov DI, [BX+IRQData] + + In AL, 0A1h + Mov AH, AL + In AL, 21h + + And AX, [BX+IRQData+2] + + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset GUSIRQOnlyHandler + + XChg [ES:DI], EAX + Mov OldIRQHandler, EAX + + StI + + Mov DX, BasePort + Mov AL, 9 ; + 16 + Out DX, AL + + Mov DX, GUSRegisterSelect + Mov AL, 4Ch + Out DX, AL + Add DL, 2 + Mov AL, 7 + Out DX, AL + + Call GetTempo + Call SetTempo + Call ResetMemory + + Mov AX, BasePort + Mov BX, IRQ + Mov CX, GUSMemory + + Mov SI, Offset GUSID2 + + ClC + Ret + +InitSound_GUS1: + Inc DL + Mov AL, 4Ch + Out DX, AL + Add DL, 2 + Mov AL, 3 ; 7 + Out DX, AL + + Mov DX, BasePort + Mov AL, 9 ; + 16 + Out DX, AL + + Mov AL, 34h ; Program IRQ 0. LSB&MSB, Rate gen + Out 43h, AL + + Call GetTempo + Call SetTempo + Call ResetMemory + + Xor AX, AX + Mov ES, AX ; ES = 0 + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset GUSIRQHandler + + ClI + + XChg DWord Ptr [ES:20h], EAX ; Clock tick + Mov OldIRQHandler, EAX + + StI + + Mov AX, BasePort + Mov BX, GUSMemory + Mov SI, Offset GUSID + + ClC + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + Push AX + + Push CS + Pop DS + Mov SI, Offset GUSReinitMsg + Mov BX, 40 + Call SetInfoLine + + Call UnInitSound + + Pop AX + Jmp InitSound + +EndP ReInitSound + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Call GotoHomeDirectory + + Push CS + Pop DS + Assume DS:Driver + +IFDEF RIC + + Mov AX, 3D02h ; Read write access + Mov DX, Offset DriverName + Int 21h + JC SaveConfig2 + + Mov BX, AX + + Mov AX, 4200h + Xor CX, CX + Mov DX, Offset CONFIGURATIONOFFSET + Int 21h + JC SaveConfig1 + + Mov AH, 40h + Mov CX, CONFIGSIZE + Mov DX, Offset Convert16To8Bit + Int 21h + +SaveConfig1: + Mov AH, 3Eh + Int 21h +SaveConfig2: + +ENDIF + Mov AX, BasePort + Call ResetGUS + + ClI + + Mov BX, CS:IRQ + Cmp BX, 0FFFFh + JE UnInitSound1 + + Mov AX, CS:IMR + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + ShL BX, 2 + Xor DI, DI + Mov ES, DI + Mov DI, [CS:BX+IRQData] + Mov EAX, CS:OldIRQHandler + + Mov [ES:DI], EAX + +; Call UnInitMIDIIRQ + + StI + Ret + +UnInitSound1: + Mov AL, 34h + Out 43h, AL + + Xor AX, AX + Out 40h, AL + Out 40h, AL + + Mov ES, AX + Mov EAX, OldIRQHandler + Mov [ES:20h], EAX + +; Call UnInitMIDIIRQ + + StI + + Ret + +EndP UnInitSound + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + Push CS + Pop DS + Assume DS:Driver + +Poll1: + Call [UARTBufferEmpty] + JNC PollEnd + + Xor BX, BX + + ClI + + Mov BL, MIDIBufferHead + Cmp BL, MIDIBufferTail + JZ PollEnd ; Nothing in queue + + Inc BL + Mov AL, [MIDIBuffer+BX] + Mov MIDIBufferHead, BL + + Call [UARTSend] + Jmp Poll1 + +PollEnd: + StI + Ret + +EndP Poll + Assume DS:Nothing + +Proc UARTOut Far + + Push DX + Push AX + + Mov DX, [CS:BasePort] + Inc DH + +UARTOut1: + In AL, DX + Test AL, 2 + JZ UARTOut1 + + Pop AX + Inc DX + + Out DX, AL + + Pop DX + + Ret + +EndP UARTOut + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far ; BX = tempo... + + Push AX + Push BX + Push DX + + Cmp CS:IRQ, 0FFFFh + JE SetTempo1 + + ShL BX, 8 + Mov DX, 1Eh + Mov AX, 8480h + Div BX + Neg AL + + Mov AH, AL + + Mov DX, CS:GUSRegisterSelect + + Mov AL, 47h + Out DX, AL + Add DL, 2 + Mov AL, AH + Out DX, AL ; Set Timer control register 2 + Sub DL, 2 + + Mov AL, 45h + Out DX, AL + Add DL, 2 + Mov AL, 8 + Out DX, AL +; Sub DL, 2 + + Mov DX, CS:BasePort + Add DL, 8 + Mov AL, 4 + Out DX, AL + + Inc DL + Mov AL, 2 + Out DX, AL + + Jmp SetTempo2 + +SetTempo1: + ; Frames per second = 2 * (0.4*Tempo) + Mov AX, 0C214h + Mov DX, 16h ; Ticks = (1193181/(2*0.4))/Tempo + Div BX + + ; AX contains counter. + Mov GUSUpdateTimer, AX + + Out 40h, AL ; Timer IRQ. + Mov AL, AH + Out 40h, AL + +SetTempo2: + Pop DX + Pop BX + Pop AX + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + Ret + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Mov CS:Stereo, AL + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc LoadSample Far + + PushAD + Push DS + Push ES + Push FS + + Mov FS, CS:SongDataArea + Mov BP, AX + Dec BP + Add BP, BP + Mov BP, [FS:64912+BP] + + Xor CX, CX ; From the start of the sample.. + Call GetSampleLocation ; Returns DS:ESI, ECX = length + JC Music_GUSLoadSampleEnd + + Mov BL, [FS:BP+12h] + Test BL, 16 + JZ Music_GUSLoadSample12 + + Cmp ECX, [FS:BP+38h] + JBE Music_GUSLoadSample12 + + Mov ECX, [FS:BP+38h] + Test BL, 32 + JZ Music_GUSLoadSample12 + + Cmp ECX, [FS:BP+44h] + JAE Music_GUSLoadSample12 + + Mov ECX, [FS:BP+44h] + +Music_GUSLoadSample12: + Mov EBX, ECX + Mov CL, CS:Compress + Mov EDX, 1 + ShR EBX, CL + ShL EDX, CL ; EDX = step value. + + Mov ECX, EBX + + ; Now find location to put it in + + Dec AX ; AX = sample number + Push AX ; AX = sample number (0 based) + + And EAX, 0FFh + Mov DWord Ptr [CS:GUSDataTable+4*EAX], 0FFFFFFFFh + + Add ECX, 2 + Mov EAX, GUSMemoryFree + + Test Byte Ptr [FS:BP+12h], 2 ; 16 bit?? + JZ Music_GUSLoadSamples13 + + Cmp CS:Convert16To8Bit, 0 + JNZ Music_GUSLoadSamples5 + + Sub EAX, 1 + JC Music_GUSLoadSampleWarning + And EAX, Not 1 ; For alignment + Add ECX, ECX + + Mov EBX, EAX + + Sub EBX, 1 + JC Music_GUSLoadSampleWarning + And EBX, 3FFFFh ; Get bytes remaining in 'segment' + Inc EBX + + Cmp ECX, 256*1024 + JAE Music_GUSLoadSamples13 + + Cmp ECX, EBX + JBE Music_GUSLoadSample2 + + Sub EAX, EBX + Jmp Music_GUSLoadSamples13 + +Music_GUSLoadSamples5: + Inc ESI + Add EDX, EDX ; Step value. + +Music_GUSLoadSamples13: + Cmp ECX, EAX + JBE Music_GUSLoadSample2 + + ; Warning msg here. +Music_GUSLoadSampleWarning: + Pop AX + +Music_GUSLoadSampleEndNoError: + ClC + Jmp Music_GUSLoadSampleEnd + +Music_GUSLoadSample3: + StC + +Music_GUSLoadSampleEnd: + Pop FS + Pop ES + Pop DS + PopAD + + Ret + +Music_GUSLoadSample2: ; EAX = number of bytes free. + ; DS:SI = sample. + ; ECX = number of bytes of memory + ; ES:DI = num bytes free ptr + ; BP = sample number. + + ; Location = MaxMem - DX:AX + ; = -(DX:AX - GUSBanks*4:0) + MovZX EBX, CS:GUSMemory + ShL EBX, 10 + ; BX = bytes avail. + Sub EBX, EAX + Sub EAX, ECX + Mov GUSMemoryFree, EAX + + Pop DI ; DI = sample number + + ShL DI, 2 + + Cmp CS:Convert16To8Bit, 0 + JNZ LoadGUSForced8Bit + + Test Byte Ptr [FS:BP+12h], 2 + JNZ Music_GUSLoad16BitSample + +LoadGUSForced8Bit: + Push EBX + Inc EBX + Mov [CS:GUSDataTable+DI], EBX ; Store pointer + + Mov ES, CS:SongDataArea + Pop EDI ; EDI = location in GUS mem + + Sub ECX, 2 + ; EDI = location in GUS mem + ; DS:SI = sample data + ; ECX = length. + ; EDX = step value. + ClI + + Push BP + + Mov EBP, EDX + + Mov AL, [DS:SI+BP] + Call LoadGUSSample + Call LoadGUSSamples + + Mov BH, AL + + Pop BP + + Mov AL, [FS:BP+12h] + Test AL, 16 + JZ Music_GUSLoadSample10 + + Mov ESI, [FS:BP+34h] + Test AL, 64 + JZ Music_GUSLoadSample11 + + Mov ESI, [FS:BP+38h] + Sub ESI, 2 + AdC ESI, 0 + + Mov EAX, Not 0 + Mov CL, CS:Compress + ShL EAX, CL + And ESI, EAX + +Music_GUSLoadSample11: + Test Byte Ptr [FS:BP+12h], 2 + JZ Music_GUSLoadSample6 + + Add ESI, ESI + Inc SI + +Music_GUSLoadSample6: + Call UpdateSampleLocation + + Mov BH, [SI] + +Music_GUSLoadSample10: + Mov AL, BH + Call LoadGUSSample + + StI + Jmp Music_GUSLoadSample3 ; Return.. no error. + +Music_GUSLoad16BitSample: + Push EBX + + Add EBX, 2 + Mov EAX, EBX + And EBX, 3FFFFh + And EAX, Not 3FFFFh + ShR EBX, 1 + Or EAX, EBX + Mov [CS:GUSDataTable+DI], EAX + + Mov ES, CS:SongDataArea + Pop EDI ; EDI = location in GUS mem + + Sub ECX, 4 + ClI + + Push BP + + Mov EBP, EDX + + Mov AX, [DS:ESI+EBP*2] + Call LoadGUSSample + Mov AL, AH + Call LoadGUSSample + + Call Load16GUSSamples + + Pop BP + + Xor BX, BX + + Mov AL, [FS:BP+12h] + Test AL, 16 + JZ Music_GUSLoad16BitSample11B + + Mov ESI, [FS:BP+34h] + + Test AL, 64 + JZ Music_GUSLoad16BitSample11 + + Mov ESI, [FS:BP+38h] + Sub ESI, 2 + JNC Music_GUSLoad16BitSample11 + + Xor ESI, ESI + +Music_GUSLoad16BitSample11: + Mov EAX, Not 0 + Mov CL, CS:Compress + ShL EAX, CL + And ESI, EAX + + Add ESI, ESI + Call UpdateSampleLocation + + Mov BX, [SI] + +Music_GUSLoad16BitSample11B: + Mov AX, BX + Call LoadGUSSample + Mov AL, AH + Call LoadGUSSample + + StI + Jmp Music_GUSLoadSample3 ; Return.. no error. + + +EndP LoadSample + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release, 0 based +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + LEA DI, [EAX*4+Offset GUSDataTable] + ; Now to release the last + ; sample from GUS memory if + ; able to. + + Cmp DWord Ptr [CS:DI], 0FFFFFFFFh + JE ReleaseSample3 + +ReleaseSample4: + MovZX EAX, CS:GUSMemory + SHL EAX, 10 + + Mov EBP, [CS:DI] ; EBP = sample pointer. + + ; If (MaxMem-(sample location in bank + sample length + 2)) = memory remaining, + ; then release memory. + + Mov ECX, [SI+30h] + Mov DL, [SI+12h] + Test DL, 16 + JZ ReleaseSample7 + + Cmp ECX, [SI+38h] + JBE ReleaseSample7 + + Mov ECX, [SI+38h] + + Test DL, 32 + JZ ReleaseSample7 + + Cmp ECX, [SI+44h] + JAE ReleaseSample7 + + Mov ECX, [SI+44h] + +ReleaseSample7: + Push EBX + Mov EBX, ECX + Mov CL, CS:Compress + ShR EBX, CL + Mov ECX, EBX + Pop EBX + + Inc ECX + Mov EDI, 1 + + Test DL, 2 + JZ ReleaseSample8Bit + + Cmp CS:Convert16To8Bit, 0 + JNZ ReleaseSample8Bit + + Add ECX, ECX + Inc DI + + ; EBP = pointer for 16 bit + ; need to convert back: + Mov EDX, EBP + Add EBP, EBP + And EBP, 3FFFFh + And EDX, Not 3FFFFh + Or EBP, EDX + +ReleaseSample8Bit: + Sub EAX, EBP + Sub EAX, ECX + + Cmp EAX, GUSMemoryFree + JNE ReleaseSample3 + + Add ECX, EDI + Add GUSMemoryFree, ECX + +ReleaseSample3: + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Push EAX + Push CX + Push ES + Push DI + + MovZX EAX, GUSMemory ; Number of kbytes + ShL EAX, 10 ; Translate to bytes + + Sub EAX, 64 ; Safety bytes. + Mov GUSMemoryFree, EAX + + Push CS + Pop ES + Mov DI, Offset GUSDataTable + Mov CX, 200 + Mov AX, 0FFFFh + Rep StosW + + Pop DI + Pop ES + Pop CX + Pop EAX + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + Push CS + Pop DS + Assume DS:Driver + + Mov EAX, GUSMemoryFree + Mov SI, Offset GUSFreeMsg + ShR EAX, 10 + +IFDEF RIC + Cmp ShowReinit, 0 + JE NoShowInit + + Mov SI, Offset GUSFreeMsg2 + Mov BX, UsedChannels + Cmp ShowReinit, 1 + JE NoShowInit + + Add BX, BX + Mov BX, [GUSMixTable+BX-28] + + NoShowInit: + +ENDIF + ClC + + Ret + +EndP GetStatus + Assume DS:Nothing + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset GUSScreenList + + ClC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far + + Ret + +EndP SetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far + + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetConvert Far + + Mov AX, [SI+22] + Mov CS:Convert16To8Bit, AL + Call Music_LoadAllSamples + + Mov AX, 1 + Ret + +EndP SetConvert + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetConvert Far + + Push CS + Pop ES + Mov DI, Offset Convert16To8Bit + Ret + +EndP GetConvert + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetCompress Far + + Mov AX, [SI+22] + Mov CS:Compress, AL + Call Music_LoadAllSamples + + Mov AX, 1 + Ret + +EndP SetCompress + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetCompress Far + + Push CS + Pop ES + Mov DI, Offset Compress + + Ret + +EndP GetCompress + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +IFDEF RIC + +Proc SetReinit Far + + Mov AX, [SI+22] + Mov CS:ShowReinit, AL + + Mov AX, 1 + Ret + +EndP SetReinit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetReinit Far + + Push CS + Pop ES + Mov DI, Offset ShowReinit + + Ret + +EndP GetReinit + +ENDIF + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Constants Table ************* + +MaxNumberOfChannels DW 32 ; Maximum number of channels the + ; driver can handle. +StopAfterPlay DW 0 +DefaultChannels DW 32 +DriverFlags DW 1 ; Driver supports MIDI Out + DW 4 Dup (0) + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + DW Offset DetectGUS + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + + DW Offset UARTOut + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End + + *********************** Notes ******************* + + UltraSound Output Structure + + 0 1 2 3 4 5 6 7 8 9 + ÚÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÂ +0000:³(Flags)³LastVol ³ + ÃÄÄÄÂÄÄÄÅÄÄÄÂÄÄÄÅÄÄÄÂÄÄÄÂÄÄÄÂÄÄÄÅÄÄÄÂÄÄÄÅ + + diff --git a/SoundDrivers/GUSDRV.ASM b/SoundDrivers/GUSDRV.ASM new file mode 100755 index 0000000..ae60f0d --- /dev/null +++ b/SoundDrivers/GUSDRV.ASM @@ -0,0 +1,5 @@ + +RAMP EQU 1 + +include gus.inc + diff --git a/SoundDrivers/GUSDRV2.ASM b/SoundDrivers/GUSDRV2.ASM new file mode 100755 index 0000000..54d73a4 --- /dev/null +++ b/SoundDrivers/GUSDRV2.ASM @@ -0,0 +1,3 @@ + +include gus.inc + diff --git a/SoundDrivers/GUSHIQ2.ASM b/SoundDrivers/GUSHIQ2.ASM new file mode 100755 index 0000000..2afcc8d --- /dev/null +++ b/SoundDrivers/GUSHIQ2.ASM @@ -0,0 +1,5 @@ + +RIC EQU 1 + +include gus.inc + diff --git a/SoundDrivers/GUSHIQDR.ASM b/SoundDrivers/GUSHIQDR.ASM new file mode 100755 index 0000000..1b46dbc --- /dev/null +++ b/SoundDrivers/GUSHIQDR.ASM @@ -0,0 +1,4 @@ +RAMP EQU 1 +RIC EQU 1 + +include gus.inc diff --git a/SoundDrivers/GUSMAX.ASM b/SoundDrivers/GUSMAX.ASM new file mode 100755 index 0000000..fbdbfd6 --- /dev/null +++ b/SoundDrivers/GUSMAX.ASM @@ -0,0 +1,2091 @@ +; +; Windows Sound System Driver +; + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;********************************** + +STEREOENABLED EQU 1 +DMABUFFERLENGTH EQU 8192 +MIXRESOLUTION EQU 32 ; 32 bit mixing for +MIXTABLESIZE EQU 2*256*65 + +DMASize DW 2048 + +WSSMsg DB "Using GUS CS4231 Codec", 13 + DB "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, DMA ", 0FDh, "D", 0 + +WSSNoMemoryMsg DB "Using GUS CS4231 Codec", 13 + DB "Error: Insufficient memory", 0 + +ReinitMsg DB "GUS Codec reinitialised", 0 + +ConfigErrorMsg DB "Error saving configuration to ITGUSMAX.DRV", 0 +ConfigOKMsg DB "Configuration saved to ITGUSMAX.DRV", 0 + +DriverName DB "ITGUSMAX.DRV", 0 + +Forced DB 0 +Stereo DB 0 +MixVolume DW 0 + +BytesToMix DW 1000 +WSSMixConst DB 0 + +MixSegment DW 0 +DMASegment DW 0 + +MixTransferOffset DW 0 +MixTransferRemaining DW 0 + +CONFIGURATIONOFFSET EQU $+128 +CONFIGSIZE EQU 6 +MixMode DW 0 +MixModeOffset DW 0 +Filter DW 0 + +IMR DW 0 +OldWSSIRQHandler DD 0 + +FilterValue DD 0 +FilterValue2 DD 0 + +MixSpeedTable DW 5513, 41h + DW 6615, 4Fh + DW 8000, 40h + DW 9600, 4Eh + DW 11025, 43h + DW 16000, 42h + DW 18900, 45h + DW 22050, 47h + DW 27429, 44h + DW 32000, 46h + DW 33075, 4Dh + DW 37800, 49h + DW 44100, 4Bh + DW 48000, 4Ch + DW 54860, 48h + DW 64000, 4Ah + +IRQData Label Word + DW 20h, 1111111111111110b ; IRQ 0 + DW 24h, 1111111111111101b ; IRQ 1 + DW 28h, 1111110111111011b ; IRQ 2 + DW 2Ch, 1111111111110111b ; IRQ 3 + DW 30h, 1111111111101111b ; IRQ 4 + DW 34h, 1111111111011111b ; IRQ 5 + DW 38h, 1111111110111111b ; IRQ 6 + DW 3Ch, 1111111101111111b ; IRQ 7 + DW 1C0h, 1111111011111011b ; IRQ 8 + DW 1C4h, 1111110111111011b ; IRQ 9 + DW 1C8h, 1111101111111011b ; IRQ 10 + DW 1CCh, 1111011111111011b ; IRQ 11 + DW 1D0h, 1110111111111011b ; IRQ 12 + DW 1D4h, 1101111111111011b ; IRQ 13 + DW 1D8h, 1011111111111011b ; IRQ 14 + DW 1DCh, 0111111111111011b ; IRQ 15 + +;********************************** +; WSS Registers +;********************************** + +CODEC_INDEX_LIC = 00 +CODEC_INDEX_RIC = 01h +CODEC_INDEX_LX1C = 02h +CODEC_INDEX_RX1C = 03h +CODEC_INDEX_LX2C = 04h +CODEC_INDEX_RX2C = 05h +CODEC_INDEX_LDC = 06h +CODEC_INDEX_RDC = 07h +CODEC_INDEX_CDF = 08h +CODEC_INDEX_INTF = 09h +CODEC_INDEX_PIN = 0Ah +CODEC_INDEX_TEST = 0Bh +CODEC_INDEX_MISC = 0Ch +CODEC_INDEX_DIGMIX = 0Dh +CODEC_INDEX_UPR_COUNT = 0Eh +CODEC_INDEX_LWR_COUNT = 0Fh + +CODEC_MCE = 40h + +LDC_LDM = 80h +LDC_LDA = 3Fh + +RDC_RDM = 80h +RDC_RDA = 3Fh + +CDF_STEREO = 10h + +INTF_PEN = 01h +INTF_CEN = 02h +INTF_SDC = 04h +INTF_ACAL = 08h +INTF_PPIO = 40h +INTF_CPIO = 80h + +PIN_IEN = 2 + +TEST_ORL = 03h +TEST_ORR = 0Ch +TEST_DRS = 10h +TEST_ACI = 20h +TEST_PUR = 40h +TEST_COR = 80h + +;********************************** + +WSS16ScreenList Label + DW 16 + DW Near Ptr IdleFunctionList + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr WSSHeaderLine + + DW Near Ptr DriverText + + DW Near Ptr MixModeText + DW Near Ptr MixModeButton1 ; 6 + DW Near Ptr MixModeButton2 ; + DW Near Ptr MixModeButton3 ; 8 + DW Near Ptr MixModeButton4 ; 9 + + DW Near Ptr FilterText + DW Near Ptr FilterButton1 ; 11 + DW Near Ptr FilterButton2 + DW Near Ptr FilterButton3 + + DW Near Ptr VolumeText + DW Near Ptr VolumeBox1 + + DW Near Ptr MasterVolumeLeft ; 16 + DW Near Ptr MasterVolumeRight ; 17 + + DW 0 + +WSSHeaderLine DW 10 + DB "GUS CS4231 Codec Driver", 0 + +EmptyObject DW 1 + DB 0, 0 + DB 0 + DB 0 + +DriverText DW 1 + DB 31, 48 + DB 21h + DB "GUS CS4231 Codec Driver 1.0 for Impulse Tracker", 0 + +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +IdleFunctionList DD 0 + DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +VolumeText DW 1 + DB 2, 14 + DB 20h + DB "Master Volume Left", 13 + DB "Master Volume Right" + DB 0 + +VolumeBox1 DW 0 + DB 21, 13, 31, 16 + DB 25 + +MasterVolumeLeft DW 9 + DB 22, 14 + DW 0, 63 + DW 9, 0 + DW 0FFFFh, 17, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +MasterVolumeRight DW 9 + DB 22, 15 + DW 0, 63 + DW 9, 1 + DW 16, 6, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +MixModeText DW 1 + DB 2, 18 + DB 20h + DB "Mixing Mode, Playback Frequency: ", 0FDh, "DHz", 0 +MixSpeed DW 48000 + +MixModeButton1 DW 2 + DW 17, 7, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment1 DW 0 + DW 0 + DW Offset SetMixMode +DriverSegment2 DW 0 + DB 3, 20, 32, 22, 8 + DB 0 + DB " 16 Bit, Non-Interpolated", 0 + +MixModeButton2 DW 2 + DW 6, 8, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment3 DW 0 + DW 2 + DW Offset SetMixMode +DriverSegment4 DW 0 + DB 3, 23, 32, 25, 8 + DB 0 + DB " 16 Bit, Interpolated", 0 + +MixModeButton3 DW 2 + DW 7, 9, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment5 DW 0 + DW 4 + DW Offset SetMixMode +DriverSegment6 DW 0 + DB 3, 26, 32, 28, 8 + DB 0 + DB " 32 Bit, Non-Interpolated", 0 + +MixModeButton4 DW 2 + DW 8, 11, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment7 DW 0 + DW 6 + DW Offset SetMixMode +DriverSegment8 DW 0 + DB 3, 29, 32, 31, 8 + DB 0 + DB " 32 Bit, Interpolated", 0 + +FilterText DW 1 + DB 2, 33 + DB 20h + DB "Filter mode", 0 + +FilterButton1 DW 2 + DW 9, 12, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment9 DW 0 + DW 0 + DW Offset SetFilter +DriverSegment10 DW 0 + DB 3, 35, 29, 37, 8 + DB 0 + DB " No Filter", 0 + +FilterButton2 DW 2 + DW 11, 13, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment11 DW 0 + DW 1 + DW Offset SetFilter +DriverSegment12 DW 0 + DB 3, 38, 29, 40, 8 + DB 0 + DB " 50% Filter", 0 + +FilterButton3 DW 2 + DW 12, 0FFFFh, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment13 DW 0 + DW 2 + DW Offset SetFilter +DriverSegment14 DW 0 + DB 3, 41, 29, 43, 8 + DB 0 + DB " 75% Filter", 0 + +VolumeTable DB 2 Dup (0) + +; ÄÄ MixingRoutines ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixBufferPos DW 0 + +include dma.inc +include mix.inc +include m12bit.mix +include m12biti.mix +include m32bit.mix +include m32biti.mix + +MixFunctionTables Label + +include m12bit.inc ; contains the tables +include m12biti.inc +include m32bit.inc +include m32biti.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +RelocationTable Label Word + DW Offset DriverSegment1, Offset DriverSegment2 + DW Offset DriverSegment3, Offset DriverSegment4 + DW Offset DriverSegment5, Offset DriverSegment6 + DW Offset DriverSegment7, Offset DriverSegment8 + DW Offset DriverSegment9, Offset DriverSegment10 + DW Offset DriverSegment11, Offset DriverSegment12 + DW Offset DriverSegment13, Offset DriverSegment14 + DW 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixMode Far + + Push CS + Pop ES + Mov DI, Offset MixMode + + Ret + +EndP GetMixMode + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetFilter Far + + Push CS + Pop ES + Mov DI, Offset Filter + + Ret + +EndP GetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetFilter Far + + Mov AX, [SI+22] + Mov CS:FilterValue, 0 + Mov CS:Filter, AX + ClI + Jmp SetMixModeChain + +EndP SetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WaitCoDec + + Push CX + + Mov CX, 0F000h + +WaitCoDec1: + In AL, DX + Test AL, AL + JNS WaitCoDec2 + Loop WaitCoDec1 + + StC + +WaitCoDec2: + Pop CX + Ret + +EndP WaitCoDec + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WaitAutoCalibration + + Push CX + Mov CX, 0F000h + +WaitAutoCalibration1: + Mov AL, CODEC_INDEX_TEST + Out DX, AL + Inc DX + In AL, DX + Dec DX + Test AL, TEST_ACI + JNZ WaitAutoCalibration2 + Loop WaitAutoCalibration1 + + StC + +WaitAutoCalibration2: + Pop CX + Ret + +EndP WaitAutoCalibration + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixMode Far + + Mov AX, [SI+22] + + ClI + + Mov CS:MixMode, AX + + Mov BX, 180 + Mul BX + Mov CS:MixModeOffset, AX + + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS:RecalculateAllVolumes + + StI + +SetMixModeChain: + Call GotoHomeDirectory + + ; Now to save config into driver file. + Push CS + Pop DS + Assume DS:Driver + + Mov AX, 3D02h ; Read write access + Mov DX, Offset DriverName + Mov SI, Offset ConfigErrorMsg + Int 21h + JC SetMixMode1 + + Mov BX, AX + + Mov AX, 4200h + Xor CX, CX + Mov DX, Offset CONFIGURATIONOFFSET + Int 21h + JC SetMixMode2 + + Mov AH, 40h + Mov CX, CONFIGSIZE + Mov DX, Offset MixMode + Int 21h + +SetMixMode2: + PushF + Mov AH, 3Eh + Int 21h + PopF + + JC SetMixMode1 + + Mov SI, Offset ConfigOKMsg + +SetMixMode1: + Mov BX, 40 + Call SetInfoLine + + Mov AX, 1 + Ret + +EndP SetMixMode + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetWSSMixConst ; Work out value.. and nearest + ; mixspeed value. + + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, CmdLineMixSpeed + Mov CX, MixSpeed + Test AX, AX + JZ GetWSSMixConst1 + + Mov CX, 64000 + Cmp AX, CX + JA GetWSSMixConst1 + + Mov CX, 8000 + Cmp AX, CX + JB GetWSSMixConst1 + + Mov CX, AX + +GetWSSMixConst1: ; CX = desired mixspeed + Mov SI, Offset MixSpeedTable + Mov DX, 16 ; 16 different available speeds + + Xor BX, BX + +GetWSSMixConst2: + LodsW + Cmp AX, BX + JB GetWSSMixConst3 + Cmp AX, CX + JA GetWSSMixConst3 + + Mov BX, AX + Mov DH, [SI] + +GetWSSMixConst3: + LodsW ; Add SI, 2 + Dec DL + JNZ GetWSSMixConst2 + + Mov MixSpeed, BX + Mov WSSMixConst, DH + + Pop DS + PopA + Ret + +EndP GetWSSMixConst + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PingWSS ; Check BasePort, DX = BasePort + ; Preserves DX, destroys AX + + Push DX + + Inc DX + Inc DX + + In AL, DX + Xor AL, AL + Out DX, AL + + Dec DX + Dec DX + Call WaitCodec + JC PingWSSFailure + + In AL, DX + Test AL, AL + JS PingWSSFailure + + Mov AL, CODEC_INDEX_MISC + Out DX, AL + Inc DX ; DX = Data port + In AL, DX + Mov AH, AL ; AH = Revision + + Xor AL, AL ; Write 0 revision + Out DX, AL + In AL, DX + And AX, 8F8Fh + Cmp AL, AH + JNE PingWSSFailure + Dec DX ; DX = AD1848 baseport + + Mov AL, CODEC_MCE or CODEC_INDEX_INTF + Out DX, AL + Inc DX + Mov AL, INTF_ACAL or INTF_SDC + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_INTF + Out DX, AL + Inc DX + Mov AL, INTF_ACAL or INTF_SDC + Out DX, AL + Dec DX + + Call WaitAutoCalibration ; Returns carry if error + ; Carry clear if none. + +; JC PingWSSFailure + + Pop DX + Ret + +PingWSSFailure: + Pop DX + + StC + Ret + + +EndP PingWSS + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far + + Push CS + Pop DS + Assume DS:Driver + + Cmp IRQ, 0FFFFh + JE DetectWSSFailure + Cmp DMA, 0FFFFh + JE DetectWSSFailure + + Mov DX, BasePort + Cmp DX, 0FFFFh + JE DetectCardFindBasePort + + Call PingWSS + JNC CheckWSSOK + +DetectWSSFailure: + StC + Ret + +DetectCardFindBasePort: + Mov DX, 31Ch + Call PingWSS + JNC DetectWSSOK + + Mov DX, 32Ch + Call PingWSS + JNC DetectWSSOK + + Mov DX, 33Ch + Call PingWSS + JNC DetectWSSOK + + Mov DX, 34Ch + Call PingWSS + JNC DetectWSSOK + + Mov DX, 35Ch + Call PingWSS + JNC DetectWSSOK + + Mov DX, 36Ch + Call PingWSS + JNC DetectWSSOK + + Mov DX, 530h + Call PingWSS + JNC DetectWSSOK + + Mov DX, 604h + Call PingWSS + JNC DetectWSSOK + + Mov DX, 0F40h + Call PingWSS + JNC DetectWSSOK + + Mov DX, 0E80h + Call PingWSS + JC DetectWSSFailure + +DetectWSSOK: + Mov BasePort, DX + +CheckWSSOK: ; Check for IRQ + Mov AL, CODEC_INDEX_RDC + Out DX, AL + Inc DX + In AL, DX + Mov AH, AL + Dec DX + + Mov AL, CODEC_INDEX_LDC + Out DX, AL + Inc DX + In AL, DX + And AX, 3F3Fh + Neg AL + Neg AH + Add AL, 3Fh + Add AH, 3Fh + Mov [Word Ptr VolumeTable], AX + + Mov EAX, 'Jeff' + ClC + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixModeTable Label Word + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + +Proc MixSamples ; Given DS:SI = info tables, CX = numchannels + + ; 1. Clean buffer + ; + update variables + ; 2. Update parameters + ; 3. Mix func + ; 4. Return + + Push CX + + Mov CX, BytesToMix + Mov ES, MixSegment + Mov DI, MIXTABLESIZE + Xor EAX, EAX + Mov DX, CX + Add CX, CX + + Mov MixTransferOffset, DI ; } Memory write + + Cmp Stereo, 0 + JE MixSamples1 + + Mov DX, CX + +MixSamples1: + Rep StosD ; } Memory write + Mov MixTransferRemaining, DX ; } + + Pop CX + +MixSamples2: + Test Byte Ptr [SI], 1 + JZ MixSamplesEnd2 + Cmp Byte Ptr [SI+36h], 100 + JE MixSamplesEnd2 + + Push CX + Mov CX, [SI] + + Test CH, 2 + JZ MixSamples3 + And Byte Ptr [SI], Not 1 + + Jmp MixSamplesEnd +; Cmp MixMode, 8 ; Is it volume ramping? +; JB MixSamplesEnd + +MixSamples3: + Test CL, 20h ; New freq? + JZ MixSamples5 + + Mov AX, [SI+10h] + Mov DX, [SI+12h] + Mov BX, MixSpeed + Cmp DX, BX + JAE MixSamplesHandleError + + Div BX + ShL EAX, 16 + Xor AX, AX + Div BX + Mov STEPVALUE, EAX + +MixSamples4: + Test CH, 1 + JZ MixSamples5 + + Mov DWord Ptr [SI+1Ch], 0 ; Current Volume = 0 + ; for volume sliding. +MixSamples5: + Test CX, 8440h ; New volume or panning? + JZ MixSamplesMix + + Xor AX, AX + Test CH, 8 ; Muted? + JNZ MixModeCommon + + Mov BX, MixMode + Add BL, Stereo + Add BX, BX + Jmp [CS:MixModeTable+BX] + +Mix0Mode: ; 16-bit mixing, no interpolation +Mix0ModeMono: ; and 16-bit mixing, interpolation + Mov AL, [SI+20h] + ShR AL, 1 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 30 ; Use left only-mixing for mono + Jmp MixModeCommon + +Mix0ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix0ModeSurround + + Mul Byte Ptr [SI+20h] ; Final volume + Add AX, 64 + ShR AX, 7 + Mov [SI+0Ch], AX ; Store into right volume + + Mov AL, 64 + Sub AL, [SI+37h] + Mul Byte Ptr [SI+20h] + Add AX, 64 + ShR AX, 7 + Mov [SI+0Eh], AX ; Left volume + + Mov CH, AL ; CH = left volume + Mov CL, [SI+0Ch] ; CL = right volume + Mov AX, 0 + + Test CX, CX + JZ MixModeCommon + + Mov AL, 30 ; Left only... + Test CL, CL + JZ MixModeCommon + + Mov AL, 60 + Test CH, CH + JZ MixModeCommon + + Mov AL, 90 + Cmp CL, CH + JZ MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix0ModeSurround: + Mov AL, [SI+20h] + ShR AL, 2 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 150 ; Surround + Jmp MixModeCommon + +Mix6ModeMono: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 8 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Test AX, AX + JZ MixModeCommon + Mov AX, 30 + Jmp MixModeCommon + +Mix6ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix6ModeSurround + + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Ch], AX ; Store into right volume + Mov BX, AX + ShL EAX, 16 + + Mov AL, 64 ; Do left volume + Sub AL, [SI+37h] ; AL = 64-FinalPan + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Eh], AX + + Mov ECX, EAX + + ; BX = right volume + ; CX = Left volume + Mov AX, 0 + Test ECX, ECX + JZ MixModeCommon + + Mov AL, 30 + Test BX, BX + JZ MixModeCommon + + Mov AL, 60 + Test CX, CX + JZ MixModeCommon + + Mov AL, 90 + Cmp CX, BX + JE MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix6ModeSurround: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 9 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + JZ MixModeCommon + Mov AX, 150 + Jmp MixModeCommon + +MixModeCommon: ; Requires AX = 30/60/90 etc. depending + ; On mixing mode type. + ; This will add 180 for 16-bit, + ; And sort out loop types. + Mov BL, [SI+0Ah] + Test Byte Ptr [SI+18h], 2 ; 16 bit? + JZ MixModeCommon1 + + Add AX, 180 + +MixModeCommon1: + Cmp BL, 8 + JB MixModeCommon3 ; No loop + JE MixModeCommon2 ; Forwards loop + + Add AX, 10 + +MixModeCommon2: + Add AX, 10 + +MixModeCommon3: + Add AX, Offset MixFunctionTables + Add AX, MixModeOffset + Mov [SI+8], AX ; Offset... + +MixSamplesMix: + Mov BX, [SI+8] ; BX = offset into + Mov EAX, [CS:BX+2] + Mov DWord Ptr PreMixFunction, EAX + Mov EAX, [CS:BX+6] + Mov DWord Ptr MixFunctionSeparateBackwards, EAX + + Mov AX, BytesToMix + Mov MixBlockSize, AX + Mov MixBufferOffset, MIXTABLESIZE + + Mov EAX, CURRENTPOSITION + Mov OLDPOSITION, EAX + + Call Word Ptr [CS:BX] + + And Word Ptr [SI], 0111100010001101b + Jmp MixSamplesEnd + +MixSamplesHandleError: + Mov Word Ptr [SI], 200h + + Test Byte Ptr [SI+3Ah], 80h + JNZ MixSamplesEnd + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Turn off channel + +MixSamplesEnd: + Pop CX + +MixSamplesEnd2: + Add SI, 128 + Dec CX + JNZ MixSamples2 + + Ret + +EndP MixSamples + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WSSIRQHandler + + PushAD + Push DS + Push ES + + ClD + + Mov AX, CS + Mov DS, AX + Assume DS:Driver + + Mov DX, [BasePort] + Add DX, 2 + In AL, DX + Test AL, 1 + JZ WSSAckIRQ2 + + Xor AL, AL + Out DX, AL + +WSSAckIRQ2: + Mov AL, 20h + Cmp IRQ, 8 + JB WSSAckIRQ1 + + Out 0A0h, AL + +WSSAckIRQ1: + Out 20h, AL + + Mov AX, MixBufferPos + Mov BX, AX + Mul DMASize + Cmp AX, DMABUFFERLENGTH + JB WSSIRQHandler2 + + Xor AX, AX + Xor BX, BX + +WSSIRQHandler2: + Inc BX + Mov MixBufferPos, BX + + CLD + + + ; OK... time to get next block + ; Check whether stereo thing is on.. + ; + LES DI, [ActualDMAPtr] + Add DI, AX + + Mov BX, DMASize ; BX = bytes required + ShR BX, 1 + ; BX = samples required + Mov BP, 8 ; Skip for mono + Mov CL, 14 ; Shift for mono + + Cmp Stereo, 0 + JE WSSIRQHandlerMono + + Mov BP, 4 ; Stereo skip value. + Dec CL + +WSSIRQHandlerMono: + Call SaveEMSPageFrame + + Cmp MixTransferRemaining, 0 + JNE WSSIRQHandler4 + Assume DS:Nothing + +WSSIRQHandler3: + Push BX + Push CX + Push BP + Push ES + Push DI + + Call Update + Call MixSamples + + Pop DI + Pop ES + Pop BP + Pop CX + Pop BX + +WSSIRQHandler4: + Mov DS, MixSegment + Mov SI, MixTransferOffset + Mov DX, BX ; DX = samples to transfer + Cmp DX, MixTransferRemaining + JBE WSSIRQHandler5 + + Mov DX, MixTransferRemaining + +WSSIRQHandler5: + Push DX + Cmp CS:Filter, 1 + JB WSSIRQHandler6 + JE WSSIRQHFilter + + Cmp CS:Stereo, 0 + JE WSSIRQ3QFilterMono + +WSSIRQ3QFilterStereo: + Push BX + + Mov EBX, FilterValue + Mov EBP, FilterValue2 + ShR DX, 1 + +WSSIRQ3QFilterStereo1: + Mov EAX, EBX + Mov ECX, EBP + Add EAX, [SI] + Add ECX, [SI+4] + SAR EAX, 1 + SAR ECX, 1 + Add EBX, EAX + Add EBP, ECX + SAR EBX, 1 + SAR EBP, 1 + + Mov EAX, EBX + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSS3QFilterStereoClip1 + Cmp EAX, 7FFFh + JG WSS3QFilterStereoClip2 + +WSSIRQ3QFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSS3QFilterStereoClip3 + Cmp EAX, 7FFFh + JG WSS3QFilterStereoClip4 + +WSSIRQ3QFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ WSSIRQ3QFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp WSSMixTransferEnd + +WSSIRQ3QFilterMono: + Push BX + + Mov EBX, FilterValue + +WSSIRQ3QFilterMono1: + Mov EAX, EBX + Add EAX, [SI] + SAR EAX, 1 + Add EBX, EAX + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL WSS3QFilterMonoClip1 + Cmp EAX, 7FFFh + JG WSS3QFilterMonoClip2 + +WSSIRQ3QFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ WSSIRQ3QFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp WSSMixTransferEnd + +WSSIRQHFilter: + Cmp CS:Stereo, 0 + JE WSSIRQHFilterMono + +WSSIRQHFilterStereo: + Push BX + + Mov EBX, FilterValue + Mov EBP, FilterValue2 + ShR DX, 1 + +WSSIRQHFilterStereo1: + Add EBX, [SI] + Add EBP, [SI+4] + + SAR EBX, 1 + SAR EBP, 1 + + Mov EAX, EBX + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSSHFilterStereoClip1 + Cmp EAX, 7FFFh + JG WSSHFilterStereoClip2 + +WSSIRQHFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSSHFilterStereoClip3 + Cmp EAX, 7FFFh + JG WSSHFilterStereoClip4 + +WSSIRQHFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ WSSIRQHFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp WSSMixTransferEnd + +WSSIRQHFilterMono: + Push BX + + Mov EBX, FilterValue + +WSSIRQHFilterMono1: + Add EBX, [SI] + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL WSSHFilterMonoClip1 + Cmp EAX, 7FFFh + JG WSSHFilterMonoClip2 + +WSSIRQHFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ WSSIRQHFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp WSSMixTransferEnd + +WSSIRQHandler6: + Mov EAX, [SI] + SAR EAX, CL + + Cmp EAX, -8000h + JL WSSIRQHandlerClip1 + Cmp EAX, 7FFFh + JG WSSIRQHandlerClip2 + +WSSIRQHandler7: + StosW ; } Memory write + + Add SI, BP + Dec DX + JNZ WSSIRQHandler6 + +WSSMixTransferEnd: + Pop DX + + Sub MixTransferRemaining, DX ; } Memory write + Sub BX, DX + JNZ WSSIRQHandler3 + + Mov MixTransferOffset, SI ; } Memory write + + Call RestoreEMSPageFrame + + Pop ES + Pop DS + PopAD + IRet + +WSSIRQHandlerClip1: + Mov AX, 8000h + Jmp WSSIRQHandler7 + +WSSIRQHandlerClip2: + Mov AX, 7FFFh + Jmp WSSIRQHandler7 + +WSSHFilterMonoClip1: + Mov AX, 8000h + Jmp WSSIRQHFilterMono2 + +WSSHFilterMonoClip2: + Mov AX, 7FFFh + Jmp WSSIRQHFilterMono2 + +WSSHFilterStereoClip1: + Mov AX, 8000h + Jmp WSSIRQHFilterStereo2 + +WSSHFilterStereoClip2: + Mov AX, 7FFFh + Jmp WSSIRQHFilterStereo2 + +WSSHFilterStereoClip3: + Mov AX, 8000h + Jmp WSSIRQHFilterStereo3 + +WSSHFilterStereoClip4: + Mov AX, 7FFFh + Jmp WSSIRQHFilterStereo3 + +WSS3QFilterMonoClip1: + Mov AX, 8000h + Jmp WSSIRQ3QFilterMono2 + +WSS3QFilterMonoClip2: + Mov AX, 7FFFh + Jmp WSSIRQ3QFilterMono2 + +WSS3QFilterStereoClip1: + Mov AX, 8000h + Jmp WSSIRQ3QFilterStereo2 + +WSS3QFilterStereoClip2: + Mov AX, 7FFFh + Jmp WSSIRQ3QFilterStereo2 + +WSS3QFilterStereoClip3: + Mov AX, 8000h + Jmp WSSIRQ3QFilterStereo3 + +WSS3QFilterStereoClip4: + Mov AX, 7FFFh + Jmp WSSIRQ3QFilterStereo3 + +EndP WSSIRQHandler + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Add DI, Offset IRQData + Mov BX, [CS:DI] + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset WSSIRQHandler + + XChg [ES:BX], EAX + Mov OldWSSIRQHandler, EAX + + Mov AX, IMR + And AX, [DI+2] + + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Pop ES + PopAD + + Ret + +EndP SetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Mov BX, [IRQData+DI] + + Mov EAX, OldWSSIRQHandler + Mov [ES:BX], EAX + + Pop ES + PopAD + + Ret + +EndP ResetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StopWSS + + Mov DX, BasePort + + Mov AL, CODEC_INDEX_INTF + Out DX, AL + Inc DX + In AL, DX + And AL, Not INTF_PEN + Out DX, AL + + Inc DX + In AL, DX + Xor AL, AL + Out DX, AL + + Dec DX + Dec DX + + Mov AL, CODEC_INDEX_PIN + Out DX, AL + Inc DX + Xor AL, AL + Out DX, AL + + Ret + +EndP StopWSS + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StartWSS + + PushA + Push ES + Push DS + + Push CS + Pop DS + Assume DS:Driver + + ; Setup DMA + Mov BX, DMASegment + Xor AX, AX + Mov DX, DMA + Mov DI, DMABUFFERLENGTH + Call SetDMA + + LES DI, ActualDMAPtr + Xor AX, AX + Mov CX, DMABUFFERLENGTH/2 + Rep StosW + + Mov MixBufferPos, 0 + Mov MixTransferRemaining, 0 + + Mov DX, BasePort + Call PingWSS + + Mov AL, CODEC_INDEX_PIN + Out DX, AL + Inc DX + Mov AL, PIN_IEN + Out DX, AL + Dec DX + + Mov AH, WSSMixConst ; Set format/frequency + Cmp Stereo, 0 + JE StartWSS1 + + Or AH, CDF_STEREO + +StartWSS1: + Mov AL, CODEC_MCE or CODEC_INDEX_CDF + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Call WaitCodec + + Mov AL, CODEC_INDEX_CDF + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Call WaitAutoCalibration + + ; Start playback + Mov AL, CODEC_INDEX_LWR_COUNT + Out DX, AL + Inc DX + + Mov AX, DMASize + ShR AX, 1 + + Cmp Stereo, 0 + JE StartWSS2 + + ShR AX, 1 + +StartWSS2: + Dec AX + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_UPR_COUNT + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_INTF + Out DX, AL + Inc DX + In AL, DX + Or AL, INTF_PEN + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_LDC + Out DX, AL + Inc DX + In AL, DX + And AL, Not LDC_LDM + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_RDC + Out DX, AL + Inc DX + In AL, DX + And AL, Not RDC_RDM + Out DX, AL + Dec DX + + Pop DS + Pop ES + PopA + + Ret + +EndP StartWSS + Assume DS:Nothing + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov SI, Offset RelocationTable + +RelocationFix: + LodsW + Test AX, AX + JZ RelocationEnd + Mov BX, AX + Mov [BX], DS + Jmp RelocationFix + + +RelocationEnd: + Call GetEMSPageFrame + Mov EMSPageFrame, AX + + In AL, 0A1h + Mov AH, AL + In AL, 21h + Mov IMR, AX + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + Call GetWSSMixConst + + Mov AX, 2643 + Mul MixSpeed + Add AX, 0FFFFh + AdC DX, 2080 + + Mov BX, (DMABUFFERLENGTH*2)/16 + Add BX, DX + + ; Allocate MixSegment first + Mov AH, 48h + + Int 21h + JNC InitSound1 + +InitSoundNoMemory: + Mov SI, Offset WSSNoMemoryMsg + Ret + +InitSound1: + Mov MixSegment, AX + Add AX, DX + Mov DMASegment, AX + + Call SetIRQ + Call GetTempo + Call SetTempo + + Mov SI, Offset WSSMsg + + Mov AX, BasePort + Mov BX, IRQ + Mov CX, DMA + + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Call ResetIRQ + Call SetIRQ + + Mov SI, Offset ReInitMsg + Mov BX, 40 + Call SetInfoLine + + Mov AL, Stereo + Call SetStereo + + Pop ES + Pop DS + PopA + + Ret + +EndP ReInitSound + Assume DS:Nothing + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, IMR + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Mov AX, MixSegment + Test AX, AX + JZ UnInitSound1 + + Mov ES, AX + Mov AH, 49h ; Release MixSegment + Int 21h + + Call StopWSS + Call ResetIRQ + +UnInitSound1: + Ret + +EndP UnInitSound + Assume DS:Nothing + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + Ret + +EndP Poll + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Push AX + Push BX + Push DX + + Push BX + + Mov AX, MixSpeed + Mov BX, AX + Xor DX, DX + + ShL AX, 1 + RCL DX, 1 ; DX:AX = Mixspeed*2 + + ShR BX, 1 ; BX = Mixspeed/2 + + Add AX, BX + AdC DX, 0 ; DX:AX = Mixspeed*2.5 + + Pop BX ; BX = tempo + Div BX + + Mov BytesToMix, AX + + Pop DX + Pop BX + Pop AX + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + PushA + Push DS + + Mov BX, AX ; BX = MixVolume + Mov CS:MixVolume, BX + + Mov AX, CS:MixSegment + Test AX, AX + JZ SetMixVolume2 + + Mov DS, AX + + Mov CX, MIXTABLESIZE/2 + Mov SI, MIXTABLESIZE-2; Starting point - working backwards + +SetMixVolume1: + Mov AX, CX + + Dec AX ; AH = volume, AL = wave value. + Xor DX, DX + XChg AH, DL ; DL = Volume, AX = wave value + CBW + + IMul DX ; DX:AX = Volume * Wave Value + ; Ranges -8192->8128 + + IMul BX ; DX:AX = Volume * Wave Value * Mixing Volume + ; Ranges -1048576->1040384 + + Add AX, 64 + AdC DX, 0 + + ShRD AX, DX, 7 + Mov [SI], AX + Sub SI, 2 + + Loop SetMixVolume1 + +SetMixVolume2: + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS: RecalculateAllVolumes + + Pop DS + PopA + + Ret + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc RecalculateAllFrequencies + + Call GetChannelTables + +RecalculateAllFrequencies1: + Or Byte Ptr [SI], 32 + + Add SI, 128 + Dec CX + JNZ RecalculateAllFrequencies1 + + Ret + +EndP RecalculateAllFrequencies + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Mov CS:Stereo, AL + Cmp CS:MixSegment, 0 + JE SetStereo1 + + Call StopWSS + Call StartWSS + + Call RecalculateAllFrequencies + +SetStereo1: + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include loadsam.inc + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset WSS16ScreenList + + ClC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far + + Xor AH, AH + Mov AL, [CS:VolumeTable+DI] + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far + + Push DS + Push DX + + Push CS + Pop DS + Assume DS:Driver + + Mov [VolumeTable+DI], AL + + Mov DX, BasePort + + Mov AL, CODEC_INDEX_LDC + Out DX, AL + Inc DX + Mov AX, 3F3Fh + Sub AX, [Word Ptr VolumeTable] + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_RDC + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Pop DX + Pop DS + Ret + +EndP SetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. + +StopAfterPlay DW 0 +DefaultChannels DW 64 + DW 5 Dup (0) + + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/GUSMAXMX.ASM b/SoundDrivers/GUSMAXMX.ASM new file mode 100755 index 0000000..73e03bb --- /dev/null +++ b/SoundDrivers/GUSMAXMX.ASM @@ -0,0 +1,1589 @@ +; +; Windows Sound System Driver, with GUS PnP detection, MMX mixing. +; + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc +include mmx.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;********************************** + +STEREOENABLED EQU 1 +DMABUFFERLENGTH EQU 8192 +MIXRESOLUTION EQU 32 ; 32 bit mixing for +OUTPUTFILTERENABLED EQU 0 + +FPSave DB 128 Dup (0) + +DMASize DW 2048 + +WSSMsg DB "GUS CS4231 Codec MMX", 13 + DB "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, DMA ", 0FDh, "D", 0 + +WSSNoMemoryMsg DB "GUS CS4231 Codec MMX", 13 + DB "Error: Insufficient memory", 0 + +ReinitMsg DB "GUS CS4231 Codec reinitialised", 0 + +DriverName DB "ITGUSMAX.MMX", 0 + +Forced DB 0 +Stereo DB 0 +MixVolume DW 0 + +BytesToMix DW 1000 +WSSMixConst DB 0 + +MixSegment DW 0 + +MixTransferOffset DW 0 +MixTransferRemaining DW 0 + +CONFIGURATIONOFFSET EQU $+128 +CONFIGSIZE EQU 4 +MixMode DW 0 +MixModeOffset DW 0 + +IMR DW 0 +OldWSSIRQHandler DD 0 + +MixSpeedTable DW 5513, 41h + DW 6615, 4Fh + DW 8000, 40h + DW 9600, 4Eh + DW 11025, 43h + DW 16000, 42h + DW 18900, 45h + DW 22050, 47h + DW 27429, 44h + DW 32000, 46h + DW 33075, 4Dh + DW 37800, 49h + DW 44100, 4Bh + DW 48000, 4Ch + DW 54860, 48h + DW 64000, 4Ah + +IRQData Label Word + DW 20h, 1111111111111110b ; IRQ 0 + DW 24h, 1111111111111101b ; IRQ 1 + DW 28h, 1111110111111011b ; IRQ 2 + DW 2Ch, 1111111111110111b ; IRQ 3 + DW 30h, 1111111111101111b ; IRQ 4 + DW 34h, 1111111111011111b ; IRQ 5 + DW 38h, 1111111110111111b ; IRQ 6 + DW 3Ch, 1111111101111111b ; IRQ 7 + DW 1C0h, 1111111011111011b ; IRQ 8 + DW 1C4h, 1111110111111011b ; IRQ 9 + DW 1C8h, 1111101111111011b ; IRQ 10 + DW 1CCh, 1111011111111011b ; IRQ 11 + DW 1D0h, 1110111111111011b ; IRQ 12 + DW 1D4h, 1101111111111011b ; IRQ 13 + DW 1D8h, 1011111111111011b ; IRQ 14 + DW 1DCh, 0111111111111011b ; IRQ 15 + +;********************************** +; WSS Registers +;********************************** + +CODEC_INDEX_LIC = 00 +CODEC_INDEX_RIC = 01h +CODEC_INDEX_LX1C = 02h +CODEC_INDEX_RX1C = 03h +CODEC_INDEX_LX2C = 04h +CODEC_INDEX_RX2C = 05h +CODEC_INDEX_LDC = 06h +CODEC_INDEX_RDC = 07h +CODEC_INDEX_CDF = 08h +CODEC_INDEX_INTF = 09h +CODEC_INDEX_PIN = 0Ah +CODEC_INDEX_TEST = 0Bh +CODEC_INDEX_MISC = 0Ch +CODEC_INDEX_DIGMIX = 0Dh +CODEC_INDEX_UPR_COUNT = 0Eh +CODEC_INDEX_LWR_COUNT = 0Fh + +CODEC_MCE = 40h + +LDC_LDM = 80h +LDC_LDA = 3Fh + +RDC_RDM = 80h +RDC_RDA = 3Fh + +CDF_STEREO = 10h + +INTF_PEN = 01h +INTF_CEN = 02h +INTF_SDC = 04h +INTF_ACAL = 08h +INTF_PPIO = 40h +INTF_CPIO = 80h + +PIN_IEN = 2 + +TEST_ORL = 03h +TEST_ORR = 0Ch +TEST_DRS = 10h +TEST_ACI = 20h +TEST_PUR = 40h +TEST_COR = 80h + +;********************************** + +WSS16ScreenList Label + DW 12 + DW Near Ptr IdleFunctionList + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr WSSHeaderLine + + DW Near Ptr DriverText + + DW Near Ptr MixModeText + DW Near Ptr MixModeButton1 ; 6 + DW Near Ptr MixModeButton2 ; + DW Near Ptr MixModeButton3 ; 8 + DW Near Ptr MixModeButton4 ; 9 + + DW Near Ptr VolumeText + DW Near Ptr VolumeBox1 + + DW Near Ptr MasterVolumeLeft ; 12 + DW Near Ptr MasterVolumeRight ; 13 + + DW 0 + + +WSSHeaderLine DW 10 + DB "GUS CS4231 Codec MMX Driver", 0 + +DriverText DW 1 + DB 28, 48 + DB 21h + DB "GUS CS4231 Codec MMX Driver 1.0 for Impulse Tracker", 0 + +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +IdleFunctionList DD 0 + DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +VolumeText DW 1 + DB 2, 14 + DB 20h + DB "Master Volume Left", 13 + DB "Master Volume Right" + DB 0 + +VolumeBox1 DW 0 + DB 21, 13, 31, 16 + DB 25 + +MasterVolumeLeft DW 9 + DB 22, 14 + DW 0, 63 + DW 9, 0 + DW 0FFFFh, 13, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +MasterVolumeRight DW 9 + DB 22, 15 + DW 0, 63 + DW 9, 1 + DW 12, 6, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +MixModeText DW 1 + DB 2, 18 + DB 20h + DB "Mixing Mode, Playback Frequency: ", 0FDh, "DHz", 0 +MixSpeed DW 48000 + DW 0 + +MixModeButton1 DW 2 + DW 13, 7, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment1 DW 0 + DW 0 + DW Offset SetMixMode +DriverSegment2 DW 0 + DB 3, 20, 32, 22, 8 + DB 0 + DB " MMX, Non-Interpolated", 0 + +MixModeButton2 DW 2 + DW 6, 8, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment3 DW 0 + DW 1 + DW Offset SetMixMode +DriverSegment4 DW 0 + DB 3, 23, 32, 25, 8 + DB 0 + DB " MMX, Interpolated", 0 + +MixModeButton3 DW 2 + DW 7, 9, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment5 DW 0 + DW 2 + DW Offset SetMixMode +DriverSegment6 DW 0 + DB 3, 26, 32, 28, 8 + DB 0 + DB " MMX, Volume Ramped", 0 + +MixModeButton4 DW 2 + DW 8, 0FFFFh, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment7 DW 0 + DW 3 + DW Offset SetMixMode +DriverSegment8 DW 0 + DB 3, 29, 32, 31, 8 + DB 0 + DB " MMX, Filtered", 0 + +VolumeTable DB 2 Dup (56) + +; ÄÄ MixingRoutines ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixBufferPos DW 0 + +include dma.inc +include mix.inc + +include m32bitm.mix +include m32bitmi.mix +include m32bitmv.mix +include m32bitmf.mix + +ALIGN 2 + +MixFunctionTables Label + +include m32bitm.inc +include m32bitmi.inc +include m32bitmv.inc +include m32bitmf.inc +include mnomix.inc + + +include nodebug.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +RelocationTable Label Word + DW Offset DriverSegment1, Offset DriverSegment2 + DW Offset DriverSegment3, Offset DriverSegment4 + DW Offset DriverSegment5, Offset DriverSegment6 + DW Offset DriverSegment7, Offset DriverSegment8 + DW 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixMode Far + + Push CS + Pop ES + Mov DI, Offset MixMode + + Ret + +EndP GetMixMode + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WaitCoDec + + Push CX + + Mov CX, 0F000h + +WaitCoDec1: + In AL, DX + Test AL, AL + JNS WaitCoDec2 + Loop WaitCoDec1 + + StC + +WaitCoDec2: + Pop CX + Ret + +EndP WaitCoDec + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WaitAutoCalibration + + Push CX + Mov CX, 0F000h + +WaitAutoCalibration1: + Mov AL, CODEC_INDEX_TEST + Out DX, AL + Inc DX + In AL, DX + Dec DX + Test AL, TEST_ACI + JNZ WaitAutoCalibration2 + Loop WaitAutoCalibration1 + + StC + +WaitAutoCalibration2: + Pop CX + Ret + +EndP WaitAutoCalibration + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixMode Far + + Trace "GUSPnP MMX: SetMixMode" + + Mov AX, [SI+22] + + ClI + + Mov CS:MixMode, AX + + Mov BX, 60 + Mul BX + Mov CS:MixModeOffset, AX + + StI + + Mov AX, 1 + Ret + +EndP SetMixMode + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetWSSMixConst ; Work out value.. and nearest + ; mixspeed value. + + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, CmdLineMixSpeed + Mov CX, MixSpeed + Test AX, AX + JZ GetWSSMixConst1 + + Mov CX, 64000 + Cmp AX, CX + JA GetWSSMixConst1 + + Mov CX, 8000 + Cmp AX, CX + JB GetWSSMixConst1 + + Mov CX, AX + +GetWSSMixConst1: ; CX = desired mixspeed + Mov SI, Offset MixSpeedTable + Mov DX, 16 ; 14 different available speeds + + Xor BX, BX + +GetWSSMixConst2: + LodsW + Cmp AX, BX + JB GetWSSMixConst3 + Cmp AX, CX + JA GetWSSMixConst3 + + Mov BX, AX + Mov DH, [SI] + +GetWSSMixConst3: + LodsW ; Add SI, 2 + Dec DL + JNZ GetWSSMixConst2 + + Mov MixSpeed, BX + Mov WSSMixConst, DH + + FNInit + FILd DWord Ptr [MixSpeed] + FMul FreqMultiplier + FStP FreqMultiplier + + + Pop DS + PopA + Ret + +EndP GetWSSMixConst + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PingWSS ; Check BasePort, DX = BasePort + ; Preserves DX, destroys AX + + Push DX + + Inc DX + Inc DX + + In AL, DX + Xor AL, AL + Out DX, AL + + Dec DX + Dec DX + Call WaitCodec + JC PingWSSFailure + + In AL, DX + Test AL, AL + JS PingWSSFailure + + Mov AL, CODEC_INDEX_MISC + Out DX, AL + Inc DX ; DX = Data port + In AL, DX + Mov AH, AL ; AH = Revision + + Xor AL, AL ; Write 0 revision + Out DX, AL + In AL, DX + And AX, 8F8Fh + Cmp AL, AH + JNE PingWSSFailure + Dec DX ; DX = AD1848 baseport + + Mov AL, CODEC_MCE or CODEC_INDEX_INTF + Out DX, AL + Inc DX + Mov AL, INTF_ACAL or INTF_SDC + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_INTF + Out DX, AL + Inc DX + Mov AL, INTF_ACAL or INTF_SDC + Out DX, AL + Dec DX + + Call WaitAutoCalibration ; Returns carry if error + ; Carry clear if none. + +; JC PingWSSFailure + + Pop DX + Ret + +PingWSSFailure: + Pop DX + + StC + Ret + + +EndP PingWSS + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectMMX + + PushFD + Pop EAX + Mov EBX, EAX + Xor EAX, 00200000h + Push EAX + PopFD + PushFD + Pop EAX + Cmp EAX, EBX + JZ DetectMMXFail + + Mov EAX, 1 + DB 0Fh, 0A2h ; CPUID + Test EDX, 800000h + JZ DetectMMXFail + + ClC + Ret + +DetectMMXFail: + StC + Ret + +EndP DetectMMX + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far ; returns carry clear if succesful + + Push CS + Pop DS + + Call DetectMMX + JC DetectWSSFailure + + Cmp IRQ, 0FFFFh + JE DetectWSSFailure + Cmp DMA, 0FFFFh + JE DetectWSSFailure + + Mov DX, BasePort + Cmp DX, 0FFFFh + JE DetectCardFindBasePort + + Call PingWSS + JNC CheckWSSOK + +DetectWSSFailure: + StC + Ret + +DetectCardFindBasePort: + Mov DX, 31Ch + Call PingWSS + JNC DetectWSSOK + + Mov DX, 32Ch + Call PingWSS + JNC DetectWSSOK + + Mov DX, 33Ch + Call PingWSS + JNC DetectWSSOK + + Mov DX, 34Ch + Call PingWSS + JNC DetectWSSOK + + Mov DX, 35Ch + Call PingWSS + JNC DetectWSSOK + + Mov DX, 36Ch + Call PingWSS + JNC DetectWSSOK + + Mov DX, 530h + Call PingWSS + JNC DetectWSSOK + + Mov DX, 604h + Call PingWSS + JNC DetectWSSOK + + Mov DX, 0F40h + Call PingWSS + JNC DetectWSSOK + + Mov DX, 0E80h + Call PingWSS + JC DetectWSSFailure + +DetectWSSOK: + Mov BasePort, DX + +CheckWSSOK: ; Check for IRQ + Mov AL, CODEC_INDEX_RDC + Out DX, AL + Inc DX + In AL, DX + Mov AH, AL + Dec DX + + Mov AL, CODEC_INDEX_LDC + Out DX, AL + Inc DX + In AL, DX + And AX, 3F3Fh + Neg AL + Neg AH + Add AL, 3Fh + Add AH, 3Fh + Mov [Word Ptr VolumeTable], AX + + Mov EAX, 'Jeff' + ClC + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include mmxmsam.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WSSIRQHandler + + PushAD + Push DS + Push ES + + ClD + + Mov AX, CS + Mov DS, AX + Assume DS:Driver + + Mov DX, [BasePort] + Add DX, 2 + In AL, DX + Test AL, 1 + JZ WSSAckIRQ2 + + Xor AL, AL + Out DX, AL + +WSSAckIRQ2: + Mov AL, 20h + Cmp IRQ, 8 + JB WSSAckIRQ1 + + Out 0A0h, AL + +WSSAckIRQ1: + Out 20h, AL + + FNSave [FPSave] + + Mov AX, MixBufferPos + Mov BX, AX + Mul DMASize + Cmp AX, DMABUFFERLENGTH + JB WSSIRQHandler2 + + Xor AX, AX + Xor BX, BX + +WSSIRQHandler2: + Inc BX + Mov MixBufferPos, BX + + CLD + + ; OK... time to get next block + ; Check whether stereo thing is on.. + ; + LES DI, [ActualDMAPtr] + Mov BX, DMASize ; BX = bytes required + Add DI, AX + + ShR BX, 1 + ; BX = samples required + Call SaveEMSPageFrame + + Cmp MixTransferRemaining, 0 + JNE WSSIRQHandler4 + Assume DS:Nothing + +WSSIRQHandler3: + Push BX + Push CX + Push BP + Push ES + Push DI + + Call Update + Call MixSamples + + Pop DI + Pop ES + Pop BP + Pop CX + Pop BX + +WSSIRQHandler4: + Mov DS, MixSegment + Mov SI, MixTransferOffset + Mov DX, BX ; DX = samples to transfer + Cmp DX, MixTransferRemaining + JBE WSSIRQHandler5 + + Mov DX, MixTransferRemaining + +WSSIRQHandler5: + +include mmxtrans.inc + + Sub MixTransferRemaining, DX ; } Memory write + Sub BX, DX + JNZ WSSIRQHandler3 + + Mov MixTransferOffset, SI ; } Memory write + + Call RestoreEMSPageFrame + + FNRstor [CS:FPSave] + + Pop ES + Pop DS + PopAD + IRet + +EndP WSSIRQHandler + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Add DI, Offset IRQData + Mov BX, [CS:DI] + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset WSSIRQHandler + + XChg [ES:BX], EAX + Mov OldWSSIRQHandler, EAX + + Mov AX, IMR + And AX, [DI+2] + + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Pop ES + PopAD + + Ret + +EndP SetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Mov BX, [IRQData+DI] + + Mov EAX, OldWSSIRQHandler + Mov [ES:BX], EAX + + Pop ES + PopAD + + Ret + +EndP ResetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StopWSS + + Trace "GUSPnP MMX: StopSound" + + Mov DX, BasePort + + Mov AL, CODEC_INDEX_INTF + Out DX, AL + Inc DX + In AL, DX + And AL, Not INTF_PEN + Out DX, AL + + Inc DX + In AL, DX + Xor AL, AL + Out DX, AL + + Dec DX + Dec DX + + Mov AL, CODEC_INDEX_PIN + Out DX, AL + Inc DX + Xor AL, AL + Out DX, AL + + Ret + +EndP StopWSS + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StartWSS + + PushA + Push ES + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Trace "GUSPnP MMX: StartSound" + + ; Setup DMA + Mov BX, MixSegment + Mov AX, 80 + Mov DX, DMA + Mov DI, DMABUFFERLENGTH + Call SetDMA + + LES DI, ActualDMAPtr + Xor AX, AX + Mov CX, DMABUFFERLENGTH/2 + Rep StosW + + Mov MixBufferPos, 0 + Mov MixTransferRemaining, 0 + + Mov DX, BasePort + Call PingWSS + + Mov AL, CODEC_INDEX_PIN + Out DX, AL + Inc DX + Mov AL, PIN_IEN + Out DX, AL + Dec DX + + Mov AH, WSSMixConst ; Set format/frequency + Cmp Stereo, 0 + JE StartWSS1 + + Or AH, CDF_STEREO + +StartWSS1: + Mov AL, CODEC_MCE or CODEC_INDEX_CDF + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Call WaitCodec + + Mov AL, CODEC_INDEX_CDF + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Call WaitAutoCalibration + + ; Start playback + Mov AL, CODEC_INDEX_LWR_COUNT + Out DX, AL + Inc DX + + Mov AX, DMASize + ShR AX, 1 + + Cmp Stereo, 0 + JE StartWSS2 + + ShR AX, 1 + +StartWSS2: + Dec AX + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_UPR_COUNT + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_INTF + Out DX, AL + Inc DX + In AL, DX + Or AL, INTF_PEN + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_LDC + Out DX, AL + Inc DX + In AL, DX + And AL, Not LDC_LDM + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_RDC + Out DX, AL + Inc DX + In AL, DX + And AL, Not RDC_RDM + Out DX, AL + Dec DX + + Pop DS + Pop ES + PopA + + Ret + +EndP StartWSS + Assume DS:Nothing + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Trace "GUSPnP MMX: InitSound" + + Mov SI, Offset RelocationTable + +RelocationFix: + LodsW + Test AX, AX + JZ RelocationEnd + Mov BX, AX + Mov [BX], DS + Jmp RelocationFix + + +RelocationEnd: + Call GetEMSPageFrame + Mov EMSPageFrame, AX + + In AL, 0A1h + Mov AH, AL + In AL, 21h + Mov IMR, AX + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + Call GetWSSMixConst + + Mov AX, 2643 + Mul MixSpeed + Add AX, 0FFFFh + AdC DX, (DMABUFFERLENGTH*2)/16 + 5 + Mov BX, DX + + ; Allocate MixSegment first + Mov AH, 48h + + Int 21h + JNC InitSound1 + +InitSoundNoMemory: + Mov SI, Offset WSSNoMemoryMsg + Ret + +InitSound1: + Mov MixSegment, AX + + Call SetIRQ + Call GetTempo + Call SetTempo + + Call UpdateSoundcardVariables + + Mov SI, Offset WSSMsg + + Mov AX, BasePort + Mov BX, IRQ + Mov CX, DMA + + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Call ResetIRQ + Call SetIRQ + + Mov SI, Offset ReInitMsg + Mov BX, 40 + Call SetInfoLine + + Mov AL, Stereo + Call SetStereo + + Pop ES + Pop DS + PopA + + Ret + +EndP ReInitSound + Assume DS:Nothing + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, IMR + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Mov AX, MixSegment + Test AX, AX + JZ UnInitSound1 + + Mov ES, AX + Mov AH, 49h ; Release MixSegment + Int 21h + + Call StopWSS + Call ResetIRQ + +UnInitSound1: + Call GotoHomeDirectory + + ; Now to save config into driver file. + Mov AX, 3D02h ; Read write access + Mov DX, Offset DriverName + Int 21h + JC SetMixMode1 + + Mov BX, AX + + Mov AX, 4200h + Xor CX, CX + Mov DX, Offset CONFIGURATIONOFFSET + Int 21h + JC SetMixMode2 + + Mov AH, 40h + Mov CX, CONFIGSIZE + Mov DX, Offset MixMode + Int 21h + +SetMixMode2: + Mov AH, 3Eh + Int 21h + +SetMixMode1: + Ret + +EndP UnInitSound + Assume DS:Nothing + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + Ret + +EndP Poll + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Push AX + Push BX + Push DX + + Push BX + + Mov AX, MixSpeed + Mov BX, AX + Xor DX, DX + + ShL AX, 1 + RCL DX, 1 ; DX:AX = Mixspeed*2 + + ShR BX, 1 ; BX = Mixspeed/2 + + Add AX, BX + AdC DX, 0 ; DX:AX = Mixspeed*2.5 + + Pop BX ; BX = tempo + Div BX + + Mov BytesToMix, AX + + Pop DX + Pop BX + Pop AX + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + Mov CS:MixVolume, AX + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Jmp CS:RecalculateAllVolumes + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc RecalculateAllFrequencies + + Call GetChannelTables + +RecalculateAllFrequencies1: + Or Byte Ptr [SI], 32 + + Add SI, 128 + Dec CX + JNZ RecalculateAllFrequencies1 + + Ret + +EndP RecalculateAllFrequencies + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Trace "GUSPnP MMX: SetStereoCall" + + Mov CS:Stereo, AL + Cmp CS:MixSegment, 0 + JE SetStereo1 + + Call StopWSS + Call StartWSS + + Call RecalculateAllFrequencies + +SetStereo1: + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include loadsam.inc + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset WSS16ScreenList + + Trace "GUSPnP MMX: Driver Screen" + + ClC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far + + Xor AH, AH + Mov AL, [CS:VolumeTable+DI] + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UpdateSoundcardVariables + + Push AX DX + + Push CS + Pop DS + Assume DS:Driver + + Mov DX, BasePort + + Mov AL, CODEC_INDEX_LDC + Out DX, AL + Inc DX + Mov AX, 3F3Fh + Sub AX, [Word Ptr VolumeTable] + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_RDC + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Pop DX AX + Ret + +EndP UpdatesoundcardVariables + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far + + Push DS + Push DX + + Push CS + Pop DS + Assume DS:Driver + + Mov [VolumeTable+DI], AL + Call UpdateSoundcardVariables + + Pop DX + Pop DS + Ret + +EndP SetVariable + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +InterpretState DB 0 +InterpretType DB 0 + +Proc SendUARTOut Far ; Local interpreter activated with 0F0h 0F0h. + + Mov AH, CS:InterpretState + Cmp AH, 2 + JB SendUARTOut1 + +; In interpreter. + JE SendUARTOut3 + +; Have InterpretType, now get parameter, then return to normal. + + Cmp AL, 7Fh + JA SendUARTOut4 + + Push BX + + Mov BL, CS:InterpretType ; Want BX = InterpretType*64+Channel + ; + ShL BX, 6 + Add BL, [DI+20h] + And BX, 127 + Mov [CS:FilterParameters+BX], AL + + Pop BX + + Test SI, SI + JZ SendUARTOut4 + + Or Byte Ptr [SI], 64 + +SendUARTOut4: + Mov CS:InterpretState, 0 + Ret + +SendUARTOut3: + Cmp AL, 2 + JAE SendUARTOut4 + + Mov CS:InterpretType, AL + Jmp SendUARTOutStateInc + +SendUARTOut1: + Cmp AL, 0F0h + JNE SendUARTOut2 + +SendUARTOutStateInc: + Inc CS:InterpretState + Ret + +SendUARTOut2: + Test AH, AH + JZ SendUARTOutEnd + + Push AX + Mov AL, 0F0h +; Call UARTOut + Pop AX + Mov CS:InterpretState, 0 + +SendUARTOutEnd: + Cmp AL, 0FCh + JE ResetFilters + Cmp AL, 0FAh + JE ResetFilters + + Cmp AL, 0FFh + JNE SendUARTOutNoClear + +ResetFilters: + PushA + Push ES + + Push CS + Pop ES + + Mov DI, Offset FilterParameters + Mov CX, 64 + Mov AL, 7Fh + Rep StosB + Mov CX, 64 + Xor AX, AX + Rep StosB + + Pop ES + PopA + +SendUARTOutNoClear: +; Call UARTOut + Ret + +EndP SendUARTOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. + +StopAfterPlay DW 0 +DefaultChannels DW 128 + DW 3 + DW 4 Dup (0) + + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + DW Offset SendUARTOut + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/GUSMIXDR.ASM b/SoundDrivers/GUSMIXDR.ASM new file mode 100755 index 0000000..853b5f5 --- /dev/null +++ b/SoundDrivers/GUSMIXDR.ASM @@ -0,0 +1,2462 @@ + + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;********************************** + +STEREOENABLED EQU 1 +DMABUFFERLENGTH EQU 4096 + +ENDLOCATIONHIGH EQU 1Fh +ENDLOCATIONLOW EQU 0FE00h +HALFENDLOCATIONHIGH EQU 0Fh +HALFENDLOCATIONLOW EQU 0FE00h + +MIXRESOLUTION EQU 32 ; 32 bit mixing for the GUS +MIXTABLESIZE EQU 2*256*65 + +Voice0Position DD 0 +Voice1Position DD 0 + +GUSMsg DB "Gravis Ultrasound detected", 13 + DB "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, DMA ", 0FDh, "D", 0 + +GUSNoMemoryMsg DB "Gravis Ultrasound detected", 13 + DB "Error: Insufficient memory", 0 + +ReinitMsg DB "Gravis Ultrasound reinitialised", 0 + +ConfigErrorMsg DB "Error saving configuration to ITGUSMIX.DRV", 0 +ConfigOKMsg DB "Configuration saved to ITGUSMIX.DRV", 0 + +DriverName DB "ITGUSMIX.DRV", 0 +UltrasndString DB "ULTRASND" + +GUSMixTable Label Word + DW 44100, 41160, 38588, 36318, 34300, 32495, 30870, 29400, 28064 + DW 26844, 25725, 24696, 23746, 22867, 22050, 21290, 20580, 19916 + DW 19294 + +DSPVersion DW 0 +DSPIRQValue DB 0 +DSPDMAValue DB 0 +Forced DB 0 +Stereo DB 0 +MixVolume DW 0 + +BytesToMix DW 1000 +MixSpeed DW 44100 +GUSChannels DB 14 + +MixSegment DW 0 +DMASegment DW 0 + +MixTransferOffset DW 0 +MixTransferRemaining DW 0 + +GUSRegisterSelect DW 0 +GUSVoiceSelect DW 0 + +CONFIGURATIONOFFSET EQU $+128 +CONFIGSIZE EQU 8 +MixMode DW 0 +MixModeOffset DW 0 +Filter DW 0 +DMASize DW 4096 + +IMR DW 0 +OldIRQHandler DD 0 + +FilterValue DD 0 +FilterValue2 DD 0 + +IRQData Label Word + DW 20h, 1111111111111110b ; IRQ 0 + DW 24h, 1111111111111101b ; IRQ 1 + DW 28h, 1111110111111011b ; IRQ 2 + DW 2Ch, 1111111111110111b ; IRQ 3 + DW 30h, 1111111111101111b ; IRQ 4 + DW 34h, 1111111111011111b ; IRQ 5 + DW 38h, 1111111110111111b ; IRQ 6 + DW 3Ch, 1111111101111111b ; IRQ 7 + DW 1C0h, 1111111011111011b ; IRQ 8 + DW 1C4h, 1111110111111011b ; IRQ 9 + DW 1C8h, 1111101111111011b ; IRQ 10 + DW 1CCh, 1111011111111011b ; IRQ 11 + DW 1D0h, 1110111111111011b ; IRQ 12 + DW 1D4h, 1101111111111011b ; IRQ 13 + DW 1D8h, 1011111111111011b ; IRQ 14 + DW 1DCh, 0111111111111011b ; IRQ 15 + + +;********************************** + +GUSScreenList Label + DW 6 + DW Near Ptr IdleFunctionList + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr GUSHeaderLine + + DW Near Ptr DriverText + + DW Near Ptr MixModeText + DW Near Ptr MixModeButton1 ; 6 + DW Near Ptr MixModeButton2 ; 7 + DW Near Ptr MixModeButton3 ; 8 + DW Near Ptr MixModeButton4 ; 9 + + DW Near Ptr FilterText + DW Near Ptr FilterButton1 ; 11 + DW Near Ptr FilterButton2 + DW Near Ptr FilterButton3 + + DW 0 + +GUSHeaderLine DW 10 + DB "Gravis Ultrasound Mixed Driver", 0 + +DriverText DW 1 + DB 30, 48 + DB 21h + DB "Gravis Ultrasound Driver 1.0 for Impulse Tracker", 0 + +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +IdleFunctionList DD 0 + DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +MixModeText DW 1 + DB 2, 13 + DB 20h + DB "Mixing Mode", 0 + +MixModeButton1 DW 2 + DW 0FFFFh, 7, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment1 DW 0 + DW 0 + DW Offset SetMixMode +DriverSegment2 DW 0 + DB 3, 15, 32, 17, 8 + DB 0 + DB " 16 Bit, Non-Interpolated", 0 + +MixModeButton2 DW 2 + DW 6, 8, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment3 DW 0 + DW 2 + DW Offset SetMixMode +DriverSegment4 DW 0 + DB 3, 18, 32, 20, 8 + DB 0 + DB " 16 Bit, Interpolated", 0 + +MixModeButton3 DW 2 + DW 7, 9, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment5 DW 0 + DW 4 + DW Offset SetMixMode +DriverSegment6 DW 0 + DB 3, 21, 32, 23, 8 + DB 0 + DB " 32 Bit, Non-Interpolated", 0 + +MixModeButton4 DW 2 + DW 8, 11, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment7 DW 0 + DW 6 + DW Offset SetMixMode +DriverSegment8 DW 0 + DB 3, 24, 32, 26, 8 + DB 0 + DB " 32 Bit, Interpolated", 0 + +FilterText DW 1 + DB 2, 28 + DB 20h + DB "Filter mode", 0 + +FilterButton1 DW 2 + DW 9, 12, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment9 DW 0 + DW 0 + DW Offset SetFilter +DriverSegment10 DW 0 + DB 3, 30, 29, 32, 8 + DB 0 + DB " No Filter", 0 + +FilterButton2 DW 2 + DW 11, 13, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment11 DW 0 + DW 1 + DW Offset SetFilter +DriverSegment12 DW 0 + DB 3, 33, 29, 35, 8 + DB 0 + DB " 50% Filter", 0 + +FilterButton3 DW 2 + DW 12, 0FFFFh, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment13 DW 0 + DW 2 + DW Offset SetFilter +DriverSegment14 DW 0 + DB 3, 36, 29, 38, 8 + DB 0 + DB " 75% Filter", 0 + +; ÄÄ MixingRoutines ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixBufferPos DW 0 +MixBufferDestination DW 0 + +include dmanai.inc ; Non-auto-initialise DMA +include mix.inc +include m12bit.mix +include m12biti.mix +include m32bit.mix +include m32biti.mix + +MixFunctionTables Label + +include m12bit.inc ; contains the tables +include m12biti.inc +include m32bit.inc +include m32biti.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +RelocationTable Label Word + DW Offset DriverSegment1, Offset DriverSegment2 + DW Offset DriverSegment3, Offset DriverSegment4 + DW Offset DriverSegment5, Offset DriverSegment6 + DW Offset DriverSegment7, Offset DriverSegment8 + DW Offset DriverSegment9, Offset DriverSegment10 + DW Offset DriverSegment11, Offset DriverSegment12 + DW Offset DriverSegment13, Offset DriverSegment14 + DW 0 + +;*********************************************** + +Proc GUSDelay + + Push AX + Push DX + + Mov DX, 300h + + In AL, DX + In AL, DX + In AL, DX + In AL, DX + In AL, DX + In AL, DX + In AL, DX + In AL, DX + + Pop DX + Pop AX + + Ret + +EndP GUSDelay + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetGUS ; AX = baseport. + + Push AX + Push DX + + Mov DX, AX + Add DX, 103h ; Select register + + Mov AL, 4Ch ; Reset global register + Out DX, AL + + Add DL, 2 ; 8 bit data + Xor AL, AL + Out DX, AL ; Reset GUS! + + Call GUSDelay + Call GUSDelay + + Mov AL, 1 + Out DX, AL + + Call GUSDelay + Call GUSDelay + + Pop DX + Pop AX + + Ret + +EndP ResetGUS + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixMode Far + + Push CS + Pop ES + Mov DI, Offset MixMode + + Ret + +EndP GetMixMode + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetFilter Far + + Push CS + Pop ES + Mov DI, Offset Filter + + Ret + +EndP GetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetFilter Far + + Mov AX, [SI+22] + Mov CS:FilterValue, 0 + Mov CS:Filter, AX + ClI + Jmp SetMixModeChain + +EndP SetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixMode Far + + Mov AX, [SI+22] + + ClI + + Mov CS:MixMode, AX + + Mov BX, 180 + Mul BX + Mov CS:MixModeOffset, AX + + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS:RecalculateAllVolumes + + StI + +SetMixModeChain: + Call GotoHomeDirectory + + ; Now to save config into driver file. + Push CS + Pop DS + Assume DS:Driver + + Mov AX, 3D02h ; Read write access + Mov DX, Offset DriverName + Mov SI, Offset ConfigErrorMsg + Int 21h + JC SetMixMode1 + + Mov BX, AX + + Mov AX, 4200h + Xor CX, CX + Mov DX, Offset CONFIGURATIONOFFSET + Int 21h + JC SetMixMode2 + + Mov AH, 40h + Mov CX, CONFIGSIZE + Mov DX, Offset MixMode + Int 21h + +SetMixMode2: + PushF + Mov AH, 3Eh + Int 21h + PopF + + JC SetMixMode1 + + Mov SI, Offset ConfigOKMsg + +SetMixMode1: + + Mov BX, 200 + Call SetInfoLine + + Mov AX, 1 + Ret + +EndP SetMixMode + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetSBMixConst ; Work out value.. and nearest + ; mixspeed value. + + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, CmdLineMixSpeed + Mov CX, MixSpeed + Test AX, AX + JZ GetSBMixConst1 + + Mov CX, 44100 + Cmp AX, CX + JA GetSBMixConst1 + + Mov CX, 12000 + Cmp AX, CX + JB GetSBMixConst1 + + Mov CX, AX + +GetSBMixConst1: + ; OK.. find number of voices to + ; achieve desired mix speed. + Mov SI, Offset GUSMixTable + Mov BL, 14 + Mov CX, 32-14 + +GetSBMixConst2: + LodsW + Cmp AX, CX + JAE GetSBMixConst3 + + Inc BL + Loop GetSBMixConst2 + +GetSBMixConst3: + Mov GUSChannels, BL + + Pop DS + PopA + Ret + +EndP GetSBMixConst + Assume DS:Nothing + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far + + Push CS + Pop DS + Assume DS:Driver + + Mov Forced, AL + + Mov SI, Offset ULTRASNDString + Mov CX, 8 + Call GetEnvironment ; Returns ES:DI, Carry if error + JC DetectCardError + + Xor DX, DX ; Baseport first. + +DetectCard1: + Mov AL, [ES:DI] + Inc DI + + Cmp AL, ',' + JE DetectCard2 + + Sub AL, '0' + JC DetectCardError + Cmp AL, '9' + JA DetectCardError + + ShL DX, 4 + Add DL, AL + Jmp DetectCard1 + +DetectCard2: + Cmp DX, 210h + JB DetectCardError + Cmp DX, 280h + JA DetectCardError + + Mov BasePort, DX + Add DX, 102h + Mov GUSVoiceSelect, DX + Inc DL + Mov GUSRegisterSelect, DX + + ; Get DMA + Xor DX, DX + +DetectCard3: + Mov AL, [ES:DI] + Inc DI + Cmp AL, ',' + JE DetectCard4 + + Sub AL, '0' + JC DetectCardError + Cmp AL, 9 + JA DetectCardError + + IMul DX, 10 + Add DL, AL + Jmp DetectCard3 + +DetectCard4: + Cmp DX, 7 + JA DetectCardError + + Mov DMA, DX + + Xor DX, DX + +DetectCard5: + Mov AL, [ES:DI] + Inc DI + Cmp AL, ',' + JE DetectCard6 + + Sub AL, '0' + JC DetectCardError + Cmp AL, 9 + JA DetectCardError + + IMul DX, 10 + Add DL, AL + Jmp DetectCard5 + +DetectCard6: + Cmp DX, 7 + JA DetectCardError + ; Wasted DMA.. + + ; IRQ.. + + Xor DX, DX + +DetectCard7: + Mov AL, [ES:DI] + Inc DI + Cmp AL, ',' + JE DetectCard8 + + Sub AL, '0' + JC DetectCardError + Cmp AL, 9 + JA DetectCardError + + IMul DX, 10 + Add DL, AL + Jmp DetectCard7 + +DetectCard8: + Cmp DX, 15 + JA DetectCardError + + Mov IRQ, DX + + Mov EAX, 'Jeff' + ClC + Ret + +DetectCardError: + StC + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixModeTable Label Word + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + +Proc MixSamples ; Given DS:SI = info tables, CX = numchannels + + ; 1. Clean buffer + ; + update variables + ; 2. Update parameters + ; 3. Mix func + ; 4. Return + + Push CX + + Mov CX, BytesToMix + Mov ES, MixSegment + Mov DI, MIXTABLESIZE + Xor EAX, EAX + Mov DX, CX + Add CX, CX + + Mov MixTransferOffset, DI ; } Memory write + + Cmp Stereo, 0 + JE MixSamples1 + + Mov DX, CX + +MixSamples1: + Rep StosD ; } Memory write + Mov MixTransferRemaining, DX ; } + + Pop CX + +MixSamples2: + Test Byte Ptr [SI], 1 + JZ MixSamplesEnd2 + Cmp Byte Ptr [SI+36h], 100 + JE MixSamplesEnd2 + + Push CX + Mov CX, [SI] + + Test CH, 2 + JZ MixSamples3 + And Byte Ptr [SI], Not 1 + + Jmp MixSamplesEnd +; Cmp MixMode, 8 ; Is it volume ramping? +; JB MixSamplesEnd + +MixSamples3: + Test CL, 20h ; New freq? + JZ MixSamples5 + + Mov AX, [SI+10h] + Mov DX, [SI+12h] + Mov BX, MixSpeed + Cmp DX, BX + JAE MixSamplesHandleError + + Div BX + ShL EAX, 16 + Xor AX, AX + Div BX + Mov STEPVALUE, EAX + +MixSamples4: + Test CH, 1 + JZ MixSamples5 + + Mov DWord Ptr [SI+1Ch], 0 ; Current Volume = 0 + ; for volume sliding. +MixSamples5: + Test CX, 8440h ; New volume or panning? + JZ MixSamplesMix + + Xor AX, AX + Test CH, 8 ; Muted? + JNZ MixModeCommon + + Mov BX, MixMode + Add BL, Stereo + Add BX, BX + Jmp [CS:MixModeTable+BX] + +Mix0Mode: ; 16-bit mixing, no interpolation +Mix0ModeMono: ; and 16-bit mixing, interpolation + Mov AL, [SI+20h] + ShR AL, 1 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 30 ; Use left only-mixing for mono + Jmp MixModeCommon + +Mix0ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix0ModeSurround + + Mul Byte Ptr [SI+20h] ; Final volume + Add AX, 64 + ShR AX, 7 + Mov [SI+0Ch], AX ; Store into right volume + + Mov AL, 64 + Sub AL, [SI+37h] + Mul Byte Ptr [SI+20h] + Add AX, 64 + ShR AX, 7 + Mov [SI+0Eh], AX ; Left volume + + Mov CH, AL ; CH = left volume + Mov CL, [SI+0Ch] ; CL = right volume + Mov AX, 0 + + Test CX, CX + JZ MixModeCommon + + Mov AL, 30 ; Left only... + Test CL, CL + JZ MixModeCommon + + Mov AL, 60 + Test CH, CH + JZ MixModeCommon + + Mov AL, 90 + Cmp CL, CH + JZ MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix0ModeSurround: + Mov AL, [SI+20h] + ShR AL, 2 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 150 ; Surround + Jmp MixModeCommon + +Mix6ModeMono: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 8 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Test AX, AX + JZ MixModeCommon + Mov AX, 30 + Jmp MixModeCommon + +Mix6ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix6ModeSurround + + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Ch], AX ; Store into right volume + Mov BX, AX + ShL EAX, 16 + + Mov AL, 64 ; Do left volume + Sub AL, [SI+37h] ; AL = 64-FinalPan + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Eh], AX + + Mov ECX, EAX + + ; BX = right volume + ; CX = Left volume + Mov AX, 0 + Test ECX, ECX + JZ MixModeCommon + + Mov AL, 30 + Test BX, BX + JZ MixModeCommon + + Mov AL, 60 + Test CX, CX + JZ MixModeCommon + + Mov AL, 90 + Cmp CX, BX + JE MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix6ModeSurround: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 9 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + JZ MixModeCommon + Mov AX, 150 + Jmp MixModeCommon + +MixModeCommon: ; Requires AX = 30/60/90 etc. depending + ; On mixing mode type. + ; This will add 180 for 16-bit, + ; And sort out loop types. + Mov BL, [SI+0Ah] + Test Byte Ptr [SI+18h], 2 ; 16 bit? + JZ MixModeCommon1 + + Add AX, 180 + +MixModeCommon1: + Cmp BL, 8 + JB MixModeCommon3 ; No loop + JE MixModeCommon2 ; Forwards loop + + Add AX, 10 + +MixModeCommon2: + Add AX, 10 + +MixModeCommon3: + Add AX, Offset MixFunctionTables + Add AX, MixModeOffset + Mov [SI+8], AX ; Offset... + +MixSamplesMix: + Mov BX, [SI+8] ; BX = offset into + Mov EAX, [CS:BX+2] + Mov DWord Ptr PreMixFunction, EAX + Mov EAX, [CS:BX+6] + Mov DWord Ptr MixFunctionSeparateBackwards, EAX + + Mov AX, BytesToMix + Mov MixBlockSize, AX + Mov MixBufferOffset, MIXTABLESIZE + + Mov EAX, CURRENTPOSITION + Mov OLDPOSITION, EAX + + Call Word Ptr [CS:BX] + + And Word Ptr [SI], 0111100010001101b + Jmp MixSamplesEnd + +MixSamplesHandleError: + Mov Word Ptr [SI], 200h + + Test Byte Ptr [SI+3Ah], 80h + JNZ MixSamplesEnd + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Turn off channel + +MixSamplesEnd: + Pop CX + +MixSamplesEnd2: + Add SI, 128 + Dec CX + JNZ MixSamples2 + + Ret + +EndP MixSamples + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GUSIRQHandler + + PushAD + Push DS + Push ES + + CLD + + Mov AX, CS + Mov DS, AX + Assume DS:Driver + + Mov AL, 20h + Cmp IRQ, 7 + JBE GUSIRQHandler1 + + Out 0A0h, AL + +GUSIRQHandler1: + Out 20h, AL + + Mov DX, BasePort + Add DL, 6 + In AL, DX + + Test AL, 20h + JZ GUSIRQHandlerEnd + + ; OK.. need to determine Cause type +GUSIRQAgain: + Mov DX, GUSRegisterSelect + Mov AL, 8Fh + Out DX, AL + Add DL, 2 + In AL, DX ; Bit 6 = waveramp IRQ + + Test AL, 80h + JZ GUSLoopIRQ + + Jmp GUSIRQHandlerEnd + +GUSLoopIRQ: ; Need to disable looping and + ; enable rollover. Set End address + ; to midpoint. + Xor MixBufferPos, 1 + JZ GUSRolloverIRQ + +; Mov MixBufferDestination, DMABUFFERLENGTH/16/2 + Mov MixBufferDestination, DMABUFFERLENGTH + + Mov DX, GUSVoiceSelect + Xor AL, AL + Out DX, AL + + Inc DX + Call GUSDelay + + Mov AL, 4 ; End address high + Out DX, AL + Mov AX, HALFENDLOCATIONHIGH + Inc DX + Out DX, AX + Dec DX + + Mov AL, 5 ; End address low + Out DX, AL + Mov AX, HALFENDLOCATIONLOW +; Cmp CS:Stereo, 0 +; JE HalfEndLocationMono +; +; Mov AX, HALFENDLOCATIONSTEREOLOW +; +; HalfEndLocationMono: + Inc DX + Out DX, AX + Dec DX + + Xor AL, AL + Out DX, AL + Mov AL, 4+32 ; 16-bit data, no loop, no IRQ. + Add DL, 2 + Out DX, AL + Call GUSDelay + Out DX, AL + Sub DL, 2 + + Mov AL, 0Dh + Out DX, AL + Mov AL, 3+4 ; Enable rollover + Add DL, 2 + Out DX, AL + Call GUSDelay + Out DX, AL + Sub DL, 2 + + Jmp GUSIRQEnd + +GUSRolloverIRQ: ; Need to disable rollover and + ; enable looping. Set End address + ; to endpoint. + Mov MixBufferDestination, 0 + + Mov DX, GUSVoiceSelect + Xor AL, AL + Out DX, AL + + Call GUSDelay + Inc DX + + Mov AL, 4 ; End address high + Out DX, AL + Mov AX, ENDLOCATIONHIGH + Inc DX + Out DX, AX + Dec DX + + Mov AL, 5 ; End location low + Out DX, AL + Mov AX, ENDLOCATIONLOW + +; Cmp Stereo, 0 +; JE EndLocationMono +; +; Mov AX, ENDLOCATIONSTEREOLOW +; +; EndLocationMono: + Inc DX + Out DX, AX + Dec DX + + Xor AL, AL + Out DX, AL + Mov AL, 4+8+32 ; 16-bit data, looping + Wavetable IRQ + Add DL, 2 + Out DX, AL + Call GUSDelay + Out DX, AL + Sub DL, 2 + + Mov AL, 0Dh + Out DX, AL + Mov AL, 3 ; Disable rollover + Add DL, 2 + Out DX, AL + Sub DL, 2 + +; Jmp GUSIRQAgain + +GUSIRQEnd: + ; OK... time to get next block + ; Check whether stereo thing is on.. + ; + LES DI, [ActualDMAPtr] + + Mov BX, DMASize ; BX = bytes required + ShR BX, 1 + ; BX = samples required + Mov BP, 8 ; Skip for mono + Mov CL, 14 ; Shift for mono + + Cmp Stereo, 0 + JE GUSIRQHandlerMono + + Mov BP, 4 ; Stereo skip value. + Dec CL + +GUSIRQHandlerMono: + Call SaveEMSPageFrame + + Cmp MixTransferRemaining, 0 + JNE GUSIRQHandler4 + Assume DS:Nothing + +GUSIRQHandler3: + Push BX + Push CX + Push BP + Push ES + Push DI + + Call Update + Call MixSamples + + Pop DI + Pop ES + Pop BP + Pop CX + Pop BX + +GUSIRQHandler4: + Mov DS, MixSegment + Mov SI, MixTransferOffset + Mov DX, BX ; DX = samples to transfer + Cmp DX, MixTransferRemaining + JBE GUSIRQHandler5 + + Mov DX, MixTransferRemaining + +GUSIRQHandler5: + Push DX + Cmp CS:Filter, 1 + JB GUSIRQHandler6 + JE GUSIRQHFilter + + Cmp CS:Stereo, 0 + JE GUSIRQ3QFilterMono + +GUSIRQ3QFilterStereo: + Push BX + + Mov EBX, FilterValue + Mov EBP, FilterValue2 + ShR DX, 1 + +GUSIRQ3QFilterStereo1: + Mov EAX, EBX + Mov ECX, EBP + Add EAX, [SI] + Add ECX, [SI+4] + SAR EAX, 1 + SAR ECX, 1 + Add EBX, EAX + Add EBP, ECX + SAR EBX, 1 + SAR EBP, 1 + + Mov EAX, EBX + SAR EAX, 13 + + Cmp EAX, -8000h + JL GUS3QFilterStereoClip1 + Cmp EAX, 7FFFh + JG GUS3QFilterStereoClip2 + +GUSIRQ3QFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL GUS3QFilterStereoClip3 + Cmp EAX, 7FFFh + JG GUS3QFilterStereoClip4 + +GUSIRQ3QFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ GUSIRQ3QFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp GUSMixTransferEnd + +GUSIRQ3QFilterMono: + Push BX + + Mov EBX, FilterValue + +GUSIRQ3QFilterMono1: + Mov EAX, EBX + Add EAX, [SI] + SAR EAX, 1 + Add EBX, EAX + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL GUS3QFilterMonoClip1 + Cmp EAX, 7FFFh + JG GUS3QFilterMonoClip2 + +GUSIRQ3QFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ GUSIRQ3QFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp GUSMixTransferEnd + +GUSIRQHFilter: + Cmp CS:Stereo, 0 + JE GUSIRQHFilterMono + +GUSIRQHFilterStereo: + Push BX + + Mov EBX, FilterValue + Mov EBP, FilterValue2 + ShR DX, 1 + +GUSIRQHFilterStereo1: + Add EBX, [SI] + Add EBP, [SI+4] + + SAR EBX, 1 + SAR EBP, 1 + + Mov EAX, EBX + SAR EAX, 13 + + Cmp EAX, -8000h + JL GUSHFilterStereoClip1 + Cmp EAX, 7FFFh + JG GUSHFilterStereoClip2 + +GUSIRQHFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL GUSHFilterStereoClip3 + Cmp EAX, 7FFFh + JG GUSHFilterStereoClip4 + +GUSIRQHFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ GUSIRQHFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp GUSMixTransferEnd + +GUSIRQHFilterMono: + Push BX + + Mov EBX, FilterValue + +GUSIRQHFilterMono1: + Add EBX, [SI] + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL GUSHFilterMonoClip1 + Cmp EAX, 7FFFh + JG GUSHFilterMonoClip2 + +GUSIRQHFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ GUSIRQHFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp GUSMixTransferEnd + +GUSIRQHandler6: + Mov EAX, [SI] + SAR EAX, CL + + Cmp EAX, -8000h + JL GUSIRQHandlerClip1 + Cmp EAX, 7FFFh + JG GUSIRQHandlerClip2 + +GUSIRQHandler7: + StosW ; } Memory write + + Add SI, BP + Dec DX + JNZ GUSIRQHandler6 + +GUSMixTransferEnd: + Pop DX + + Sub MixTransferRemaining, DX ; } Memory write + Sub BX, DX + JNZ GUSIRQHandler3 + + Mov MixTransferOffset, SI ; } Memory write + + ; DMA the data to MixBufferDestination + Comment ~ + + Mov AX, CS + Mov DS, AX + Assume DS:Driver + + Mov BX, DMASegment + Xor AX, AX + Mov DX, DMA + Mov DI, DMABUFFERLENGTH + Call SetDMA + + Mov DX, GUSRegisterSelect + Mov AL, 42h ; DMA destination + Out DX, AL + Mov AX, MixBufferDestination + Inc DX + Out DX, AX + Dec DX + + Mov AL, 41h ; DMA control register + Out DX, AL + Mov AL, 1 + Cmp DMA, 4 + JB DMAType + + Or AL, 4 + +DMAType: + Add DL, 2 + Out DX, AL + + ~ + +; Comment ~ + + LDS SI, [ActualDMAPtr] + Mov DX, GUSRegisterSelect + + Mov AL, 44h + Out DX, AL ; High address + Xor AL, AL + Add DL, 2 + Out DX, AL + Sub DL, 2 + + Mov DI, MixBufferDestination + Mov CX, DMASize + + Mov AL, 43h + Out DX, AL + Inc DX + +Output1: + Mov AX, DI + Out DX, AX + Add DL, 3 + + Mov AL, [SI] + Out DX, AL + + Sub DL, 3 + Inc SI + Inc DI + Dec CX + JNZ Output1 + +; ~ + + Call RestoreEMSPageFrame + +GUSIRQHandlerEnd: + Pop ES + Pop DS + PopAD + IRet + Assume DS:Nothing + +GUSIRQHandlerClip1: + Mov AX, 8000h + Jmp GUSIRQHandler7 + +GUSIRQHandlerClip2: + Mov AX, 7FFFh + Jmp GUSIRQHandler7 + +GUSHFilterMonoClip1: + Mov AX, 8000h + Jmp GUSIRQHFilterMono2 + +GUSHFilterMonoClip2: + Mov AX, 7FFFh + Jmp GUSIRQHFilterMono2 + +GUSHFilterStereoClip1: + Mov AX, 8000h + Jmp GUSIRQHFilterStereo2 + +GUSHFilterStereoClip2: + Mov AX, 7FFFh + Jmp GUSIRQHFilterStereo2 + +GUSHFilterStereoClip3: + Mov AX, 8000h + Jmp GUSIRQHFilterStereo3 + +GUSHFilterStereoClip4: + Mov AX, 7FFFh + Jmp GUSIRQHFilterStereo3 + +GUS3QFilterMonoClip1: + Mov AX, 8000h + Jmp GUSIRQ3QFilterMono2 + +GUS3QFilterMonoClip2: + Mov AX, 7FFFh + Jmp GUSIRQ3QFilterMono2 + +GUS3QFilterStereoClip1: + Mov AX, 8000h + Jmp GUSIRQ3QFilterStereo2 + +GUS3QFilterStereoClip2: + Mov AX, 7FFFh + Jmp GUSIRQ3QFilterStereo2 + +GUS3QFilterStereoClip3: + Mov AX, 8000h + Jmp GUSIRQ3QFilterStereo3 + +GUS3QFilterStereoClip4: + Mov AX, 7FFFh + Jmp GUSIRQ3QFilterStereo3 + +EndP GUSIRQHandler + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + + PushAD + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Add DI, Offset IRQData + Mov BX, [DI] + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset GUSIRQHandler + + XChg [ES:BX], EAX + Mov OldIRQHandler, EAX + + Mov AX, IMR + And AX, [DI+2] + + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Pop ES + Pop DS + PopAD + + Ret + +EndP SetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIRQ + + PushAD + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Mov BX, [IRQData+DI] + + Mov EAX, OldIRQHandler + Mov [ES:BX], EAX + + Pop ES + Pop DS + PopAD + + Ret + +EndP ResetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StartGUS ; + + PushA + Push ES + + Push CS + Pop DS + Assume DS:Driver + + ; Setup DMA + Mov BX, DMASegment + Xor AX, AX + Mov DX, DMA + Mov DI, DMABUFFERLENGTH + Call SetDMA + + LES DI, ActualDMAPtr + Xor AX, AX + Mov CX, DMABUFFERLENGTH/2 + Rep StosW + + Mov MixBufferPos, 0 + Mov MixTransferRemaining, 0 + + Mov DX, BasePort + Mov AL, 1 + Out DX, AL + + Mov AX, DX + Call ResetGUS + + Mov DX, GUSRegisterSelect ; Tell the GUS how many voices + Mov AL, 0Eh ; to use + Out DX, AL + + Add DL, 2 ; DX = BasePort + 105h + Mov AL, GUSChannels + Dec AL + Or AL, 0C0h + Out DX, AL ; Number of Voices set + + ; Reset each voice + + Mov CX, 32 ; 32 voices to clear. + + Sub DL, 3 ; DX = Voice select register + +GUSResetVoice: + Mov AL, CL + Dec AL + Out DX, AL + + Inc DX ; DX = BasePort + 103h + Xor AL, AL ; Voice control register, 8 bit + Out DX, AL + + Add DL, 2 + Mov AL, 2 + Out DX, AL ; Stop voice + Call GUSDelay + Out DX, AL + Sub DL, 2 + + Mov AL, 0Dh ; Volume Ramp. + Out DX, AL + + Mov AL, 3 + Add DL, 2 + Out DX, AL + Call GUSDelay + Out DX, AL + Sub DL, 2 + + + Mov AL, 6 ; Ramp rate + Out DX, AL + + Mov AL, 63 ; Ramp rate + Add DL, 2 + Out DX, AL + Sub DL, 2 + + + Mov AL, 9 ; Volume register, 16 bit + Out DX, AL + + Inc DX + Xor AX, AX + Out DX, AX ; No volume + Call GUSDelay + Out DX, AX + + Sub DL, 2 ; DX = BasePort + 102h = Voice select. + + Loop GUSResetVoice + + ; OK.. now... gotta clear memory from + ; 0->DMABUFFERLENGTH*2 + + Mov CX, DMABUFFERLENGTH*2 + Xor DI, DI ; DI = destination + + ClI + + Inc DX ; DX = register select + Mov AL, 44h + Out DX, AL + + Xor AL, AL + Add DL, 2 + Out DX, AL + Sub DL, 2 + + Mov AL, 43h + Out DX, AL + Inc DX + +ClearGUSRAM: + Mov AX, DI ; Memory location low + Out DX, AX ; Memory location done. + + Xor AL, AL + Add DL, 3 + Out DX, AL + Sub DL, 3 + + Inc DI + Dec CX + JNZ ClearGUSRAM + + StI + ; OK.. enable interrupt + Mov DX, BasePort + Mov AL, 9 + Out DX, AL ; Enables DMA/IRQ + + Mov DX, GUSRegisterSelect + Mov AL, 4Ch + Out DX, AL + Add DL, 2 + Mov AL, 7 + Out DX, AL ; Enables IRQ + + ; Setup voices + ClI + Cmp Stereo, 0 + JE StartGUSMono + +StartGUSStereo: ; Uses voices 0 and 1 + Mov DX, GUSVoiceSelect + Xor AL, AL + Out DX, AL + Call GUSDelay + Inc DX + + Mov AL, 1 ; Freq control + Out DX, AL + Inc DX + Mov AX, 0000100000000000b + Out DX, AX + Dec DX + + Mov AL, 2 ; Starting location high + Out DX, AL + Xor AX, AX + Inc DX + Out DX, AX + Dec DX + + Mov AL, 3 ; Starting location low + Out DX, AL + Xor AX, AX + Inc DX + Out DX, AX + Dec DX + + Mov AL, 4 ; End location high + Out DX, AL + Mov AX, HALFENDLOCATIONHIGH + Xor AX, AX + Inc DX + Out DX, AX + Dec DX + + Mov AL, 5 ; End location low + Out DX, AL + Mov AX, HALFENDLOCATIONLOW + Inc DX + Out DX, AX + Dec DX + + Mov AL, 9 ; Current volume + Out DX, AL + Mov AX, 0EFF0h + Inc DX + Out DX, AX + Call GUSDelay + Out DX, AX + Dec DX + + Mov AL, 0Ah ; Current location high + Out DX, AL + Xor AX, AX + Inc DX + Out DX, AX + Dec DX + + Mov AL, 0Bh ; Current location low + Out DX, AL + Xor AX, AX + Inc DX + Out DX, AX + Dec DX + + Mov AL, 0Ch ; Pan position + Out DX, AL + Mov AL, 0 ; Full left. + Add DL, 2 + Out DX, AL + Sub DL, 2 + + Mov AL, 0Dh ; Set rollover condition + Out DX, AL + Mov AL, 4+2+1 ; Rollover + Add DL, 2 + Out DX, AL + Sub DL, 2 + + Mov DX, GUSVoiceSelect + Mov AL, 1 ; Voice 1 + Out DX, AL + Call GUSDelay + Inc DX + + Mov AL, 1 ; Freq control + Out DX, AL + Inc DX + Mov AX, 0000100000000000b + Out DX, AX + Dec DX + + Mov AL, 2 ; Starting location high + Out DX, AL + Xor AX, AX + Inc DX + Out DX, AX + Dec DX + + Mov AL, 3 ; Starting location low + Out DX, AL + Mov AX, 0000001000000000b + Xor AX, AX + Inc DX + Out DX, AX + Dec DX + + Mov AL, 4 ; End location high + Out DX, AL + Mov AX, 20h ; ENDLOCATIONHIGH + Inc DX + Out DX, AX + Dec DX + + Mov AL, 5 ; End location low + Out DX, AL + Mov AX, 0 ; ENDLOCATIONLOW + Inc DX + Out DX, AX + Dec DX + + Mov AL, 9 ; Current volume + Out DX, AL + Mov AX, 0EFF0h + Inc DX + Out DX, AX + Call GUSDelay + Out DX, AX + Dec DX + + Mov AL, 0Ah ; Current location high + Out DX, AL + Xor AX, AX + Inc DX + Out DX, AX + Dec DX + + Mov AL, 0Bh ; Current location low + Out DX, AL + Mov AX, 0000001000000000b + Inc DX + Out DX, AX + Dec DX + + Mov AL, 0Ch ; Pan position + Out DX, AL + Mov AL, 0Fh ; Full right + Add DL, 2 + Out DX, AL + Sub DL, 2 + ; start voices. + + Mov AL, 0Dh + Out DX, AL + Mov AL, 3 + Add DL, 2 + Out DX, AL + Sub DL, 2 + + CLI + + Mov DX, GUSVoiceSelect ; Select voice 0 + Xor AL, AL + Out DX, AL + +; Call GUSDelay + + Inc DX + Out DX, AL + Mov AL, 4+32 ; 16-bit data, IRQ enabled + Add DL, 2 + Out DX, AL + +; Call GUSDelay +; Out DX, AL + + Sub DL, 3 + + Mov AL, 1 ; Select voice 1 + Out DX, AL + +; Call GUSDelay + + Inc DX + Xor AL, AL + Out DX, AL + Mov AL, 4+8 ; 16-bit, Loop + Add DL, 2 + Out DX, AL + +; Call GUSDelay +; Out DX, AL + + Jmp StartGUSEnd + +StartGUSMono: ; Uses voice 0 + Mov DX, GUSVoiceSelect + Xor AL, AL + Out DX, AL + Call GUSDelay + Inc DX + + Mov AL, 1 ; Freq control + Out DX, AL + Inc DX + Mov AX, 0000010000000000b + Out DX, AX + Dec DX + + Mov AL, 2 ; Starting location high + Out DX, AL + Xor AX, AX + Inc DX + Out DX, AX + Dec DX + + Mov AL, 3 ; Starting location low + Out DX, AL + Xor AX, AX + Inc DX + Out DX, AX + Dec DX + + Mov AL, 4 ; End location high + Out DX, AL + Mov AX, HALFENDLOCATIONHIGH + Xor AX, AX + Inc DX + Out DX, AX + Dec DX + + Mov AL, 5 ; End location low + Out DX, AL + Mov AX, HALFENDLOCATIONLOW + Inc DX + Out DX, AX + Dec DX + + Mov AL, 9 ; Current volume + Out DX, AL + Mov AX, 0EFF0h + Inc DX + Out DX, AX + Dec DX + + Mov AL, 0Ah ; Current location high + Out DX, AL + Xor AX, AX + Inc DX + Out DX, AX + Dec DX + + Mov AL, 0Bh ; Current location low + Out DX, AL + Xor AX, AX + Inc DX + Out DX, AX + Dec DX + + Mov AL, 0Ch ; Pan position + Out DX, AL + Mov AL, 8 ; Central. + Add DL, 2 + Out DX, AL + Sub DL, 2 + + Mov AL, 0Dh ; Set rollover condition + Out DX, AL + Mov AL, 4+2+1 ; Rollover + Add DL, 2 + Out DX, AL + Sub DL, 2 + + Xor AL, AL + Out DX, AL + Mov AL, 4+32 ; 16-bit data, IRQ enabled + Add DL, 2 + Out DX, AL + Call GUSDelay + Out DX, AL + +StartGUSEnd: + StI + + Pop ES + PopA + + Ret + + +EndP StartGUS + Assume DS:Nothing + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov SI, Offset RelocationTable + +RelocationFix: + LodsW + Test AX, AX + JZ RelocationEnd + Mov BX, AX + Mov [BX], DS + Jmp RelocationFix + +RelocationEnd: + Mov AX, BasePort + Call ResetGUS + + ; SetupMIDI + Mov DX, BasePort + Inc DH + Mov AL, 0FFh + Out DX, AL + Mov AL, 0FCh + Out DX, AL + + Call GetEMSPageFrame + Mov EMSPageFrame, AX + + In AL, 0A1h + Mov AH, AL + In AL, 21h + Mov IMR, AX + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + ; Allocate MixSegment first + Mov AH, 48h + Mov BX, 3859+(DMABUFFERLENGTH*2)/16 + ; 3859 = (256*2*65+8*44100/(.4*31))/16 + Int 21h + JNC InitSound1 + +InitSoundNoMemory: + Mov SI, Offset GUSNoMemoryMsg + Ret + +InitSound1: + Mov MixSegment, AX + Add AX, 3859 + Mov DMASegment, AX + + Call SetIRQ + Call GetSBMixConst + Call GetTempo + Call SetTempo + + Mov SI, Offset GUSMsg + + Mov AX, BasePort + Mov BX, IRQ + Mov CX, DMA + + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Call ResetIRQ + Call SetIRQ + + Mov SI, Offset ReInitMsg + Mov BX, 200 + Call SetInfoLine + + Mov AL, Stereo + Call SetStereo + + Pop ES + Pop DS + PopA + + Ret + +EndP ReInitSound + Assume DS:Nothing + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Mov AX, BasePort + Call ResetGUS + + Mov DX, BasePort + Inc DH + Mov AL, 0FFh + Out DX, AL ; Stop MIDI + + Mov AX, IMR + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Mov AX, MixSegment + Test AX, AX + JZ UnInitSound1 + + Mov ES, AX + Mov AH, 49h ; Release MixSegment + Int 21h + + Call ResetIRQ + +UnInitSound1: + Ret + +EndP UnInitSound + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + Mov DX, CS:GUSVoiceSelect + Xor AL, AL + Out DX, AL + Inc DX + Mov AL, 8Ah + Out DX, AL + Inc DX + In AX, DX + ShL EAX, 16 + Dec DX + Mov AL, 8Bh + OUt DX, AL + Inc DX + In AX, DX + ShR EAX, 9 + Mov CS:Voice0Position, EAX + + Mov DX, CS:GUSVoiceSelect + Mov AL, 1 + Out DX, AL + Inc DX + Mov AL, 8Ah + Out DX, AL + Inc DX + In AX, DX + ShL EAX, 16 + Dec DX + Mov AL, 8Bh + OUt DX, AL + Inc DX + In AX, DX + ShR EAX, 9 + Mov CS:Voice1Position, EAX + + Call [CS:UARTBufferEmpty] + JNC MIDIEnd + + Mov DX, [CS:BasePort] + Inc DH + In AL, DX + Test AL, 1 + JZ MIDIEnd + + Inc DX + In AL, DX + Cmp AL, 0F0h + JAE MIDIEnd + + Call [CS:UARTSend] + +MIDIEnd: + + Ret + +EndP Poll + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Push AX + Push BX + Push DX + + Push BX + + Mov AX, MixSpeed + Mov BX, AX + Xor DX, DX + + ShL AX, 1 + RCL DX, 1 ; DX:AX = Mixspeed*2 + + ShR BX, 1 ; BX = Mixspeed/2 + + Add AX, BX + AdC DX, 0 ; DX:AX = Mixspeed*2.5 + + Pop BX ; BX = tempo + Div BX + + Mov BytesToMix, AX + + Pop DX + Pop BX + Pop AX + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + PushA + Push DS + + Mov BX, AX ; BX = MixVolume + Mov CS:MixVolume, BX + + Mov AX, CS:MixSegment + Test AX, AX + JZ SetMixVolume2 + + Mov DS, AX + + Mov CX, MIXTABLESIZE/2 + Mov SI, MIXTABLESIZE-2; Starting point - working backwards + +SetMixVolume1: + Mov AX, CX + + Dec AX ; AH = volume, AL = wave value. + Xor DX, DX + XChg AH, DL ; DL = Volume, AX = wave value + CBW + + IMul DX ; DX:AX = Volume * Wave Value + ; Ranges -8192->8128 + + IMul BX ; DX:AX = Volume * Wave Value * Mixing Volume + ; Ranges -1048576->1040384 + + Add AX, 64 + AdC DX, 0 + + ShRD AX, DX, 7 + Mov [SI], AX + Sub SI, 2 + + Loop SetMixVolume1 + +SetMixVolume2: + Pop DS + PopA + + Ret + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Cmp CS:MixSegment, 0 + JE SetStereo1 + + Mov CS:Stereo, AL + Call StartGUS + +SetStereo1: + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include loadsam.inc + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset GUSScreenList + + ClC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far ; Returns AX, given DI + + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far ; Given AX, DI + + Ret + +EndP SetVariable + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. + +StopAfterPlay DW 0 +DefaultChannels DW 64 + DW 5 Dup (0) + + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/GUSNRAMP.INC b/SoundDrivers/GUSNRAMP.INC new file mode 100755 index 0000000..02020e2 --- /dev/null +++ b/SoundDrivers/GUSNRAMP.INC @@ -0,0 +1,27 @@ +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetGUSVolume ; BX = new volume + + ; To do: + ; 1) Set ramp start + ; 2) Set ramp end + ; 3) Set current volume + ; 4) Start ramp + ; 5) Save new volume. + + Mov AL, 9 + Out DX, AL + + Add BX, BX + Mov AX, [CS:GUSVolumeTable+BX] + Inc DX + Out DX, AX + Call GUSDelay + Out DX, AX + Dec DX + + Ret + +EndP SetGUSVolume + + diff --git a/SoundDrivers/GUSNRIC.INC b/SoundDrivers/GUSNRIC.INC new file mode 100755 index 0000000..3863e2f --- /dev/null +++ b/SoundDrivers/GUSNRIC.INC @@ -0,0 +1,415 @@ +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetGUSRegisters ; Given DS:SI, CX + + Mov ES, CS:SongDataArea + + Push CX + Push SI + + Xor AX, AX + +GetOffsetLoop: + Push AX + Push CX + + Mov DX, GUSVoiceSelect + Out DX, AL ; OK.. now to play with this + ; voice. + Call GUSDelay + + Inc DL ; DX = select rego + + Mov BX, [SI] + Test BH, 2 + JZ GetOffsetLoop2 + + Mov BX, 200h + Mov [SI], BX + +GetOffsetLoop2: + Test BL, 1 ; Channel not on! + JZ GetOffsetLoop1 + Test BH, 1 + JZ GetOffsetLoop3 ; Prev 1. + + Xor BX, BX + Call SetGUSVolume + + Mov AL, 80h + Out DX, AL + Add DL, 2 + In AL, DX + Sub DL, 2 + Mov AH, AL + And AX, 400h + Out DX, AL ; AL = 0 (Mode control) + Mov AL, 3 + Or AL, AH + Add DL, 2 + Out DX, AL + Call GUSDelay + Out DX, AL + Sub DL, 2 + + Jmp GetOffsetLoop1 + +GetOffsetLoop3: + Mov EAX, [SI+4Ch] + Mov [SI+2Ch], EAX + + Mov AL, 8Ah + Out DX, AL + + Inc DX + In AX, DX + Dec DX + + And AH, 31 + ShL EAX, 16 ; Load high part of EAX + + Mov AL, 8Bh + Out DX, AL + Inc DX + In AX, DX + ; EAX = 000OOOOO OOOOOOOO OOOOOOOF FFFFFFFF + ; Need: 00000000 0000OOOO OOOOOOOO OOOOOOOO + + ShR EAX, 9 + ; EAX contains current loc. + ; Convert to Offset (in sample) + MovZX EBX, Byte Ptr [SI+36h] + Sub EAX, [CS:GUSDataTable+EBX*4] + Push CX + + Mov CL, CS:Compress + ShL EAX, CL + + Pop CX + Mov [SI+4Ch], EAX + +GetOffsetLoop1: + Add SI, SLAVECHANNELSIZE + + Pop CX + Pop AX + + Inc AX + Loop GetOffsetLoop + + Pop SI + Pop CX + + Xor AX, AX + +SetGUSRegisters1: + Push AX + Push CX + + Mov DX, GUSVoiceSelect + Out DX, AL ; OK.. now to play with this + ; voice. + Call GUSDelay + + Mov CX, [SI] ; CX = flags. + Inc DL ; DX = select rego + +SetGUSRegisters21: + Test CL, 32 ; Frequency change + JZ SetGUSRegisters7 + + Push DX + + Mov EAX, [SI+10h] ; EAX = freq. + + Push CX + Mov CL, CS:Compress + ShR EAX, CL + Pop CX + + Xor EDX, EDX + MovZX EBX, MixSpeed + + Div EBX ; EAX = I portion. + + Test EAX, Not 63 + JNZ SetGUSRegisters6 + + Push EAX + + Xor EAX, EAX + Div EBX + + Pop EBX ; EBX:EAX = IIII FFFF etc. + + SHRD EAX, EBX, 6 + + ; Have: IIIIIIII IIIIIIII FFFFFFFF FFFFFFFF + ; Req: IIIIIIFF FFFFFFF0 + + Pop DX + Mov AL, 1 + Out DX, AL + + ShR EAX, 16 + Add AX, 1 + SBB AX, 0 ; Just in case! + And AX, Not 1 + + Inc DX + Out DX, AX + Dec DX + + Jmp SetGUSRegisters7 + +SetGUSRegisters6: + Mov CH, 2 ; Signify to turn off channel + Pop DX + +SetGUSRegisters7: + MovZX BX, Byte Ptr [SI+36h] ; BX = sample number. + Cmp BL, 99 + JA SetGUSRegisters20 + + ShL BX, 2 ; GUSDataTable+BX = position + + Cmp DWord Ptr [CS:GUSDataTable+BX], 0FFFFFFFFh + JNE SetGUSRegisters10 + +SetGUSRegisters20: + Mov CH, 2 + Jmp SetGUSRegisters9 + +SetGUSRegisters10: + Test CH, 5 ; Loop changed?!??!? + JZ SetGUSRegisters8 + + Mov AL, 3 ; Starting location low. + Out DX, AL + + Mov EAX, [SI+40h] + Call GUSGetAddress + + ; Reqd: ...OOOOO OOOOOOOO OOOOOOOI III..... + + Inc DX + Out DX, AX + Dec DX + + Mov AL, 2 ; Starting location high + Out DX, AL + + ShR EAX, 16 + Inc DX + Out DX, AX + Dec DX + + ; Ending location... + Mov AL, 5 ; Ending location low + Out DX, AL + + Mov EAX, [SI+44h] + Call GUSGetAddress + + Inc DX + Out DX, AX + Dec DX + + Mov AL, 4 ; Ending location high + Out DX, AL + + SHR EAX, 16 + Inc DX + Out DX, AX + Dec DX + +SetGUSRegisters8: + Test CH, 1 ; Do Current position? + JZ SetGUSRegisters9 + + Mov AL, 0Bh ; Current location LOW + Out DX, AL + + Mov EAX, [SI+4Ch] + Mov [SI+2Ch], EAX + + ; EAX = OOOOOOOO OOOOOOOO OOOOOOOO OOOOOOOO + ; Req: xxxOOOOO OOOOOOOO OOOOOOOF FFFFFFFF + Call GUSGetAddress + + Mov DI, AX + + Inc DX + Out DX, AX + Dec DX + + Mov AL, 0Ah ; Current location HIGH + Out DX, AL + + SHR EAX, 16 + Inc DX + Out DX, AX + Call GUSDelay + Out DX, AX + Dec DX + + Mov AL, 0Bh + Out DX, AL + + Mov AX, DI + Inc DX + Out DX, AX + Dec DX + +SetGUSRegisters9: + Test CL, 64 ; New volume?? + JZ SetGUSPanning + +SetGUSRegisters23: + Xor BX, BX + Test CH, 8 + JNZ SetGUSRegistersMuted + + Mov BL, Byte Ptr [SI+20h] ; BL = volume, 0->128 + +SetGUSRegistersMuted: + Call SetGUSVolume + + +SetGUSPanning: + Test CH, 128 ; New panning? + JZ SetGUSRegisters5 + + Mov AL, 0Ch ; Set panning. + Out DX, AL + + Test CS:Stereo, 1 + JZ SetGUSRegisters3 + + Mov AL, [SI+37h] + Cmp AL, 100 + JNE SetGUSRegisters4 + +SetGUSRegisters3: + Mov AL, 32 ; Surround goes to mono :( + +SetGUSRegisters4: ; AL = 0->64 + ShR AL, 1 ; AL = 0->32 + Sub AL, 1 + AdC AL, 0 ; AL = 0->31 + ShR AL, 1 + + Add DL, 2 + Out DX, AL + Sub DL, 2 + +SetGUSRegisters5: + ; Now for control register. + ; If CH | 2, then turn rego OFF + ; If CH | 5, then turn rego ON + ; If CL | 1, then check channel + Test CH, 2 + JNZ SetGUSRegisters11 + + Test CH, 5 + JNZ SetGUSRegisters12 + + Test CL, 1 + JZ SetGUSRegisters13 + + Mov AL, 80h ; Read voice control + Out DX, AL + + Add DL, 2 + In AL, DX + Sub DL, 2 + + Test AL, 1 + JZ SetGUSRegisters13 + + Xor BX, BX + Call SetGUSVolume + + Jmp SetGUSRegisters14 + +SetGUSRegisters11: + ; Turn off. + Xor AL, AL + Out DX, AL ; AL = 0 (Mode control) + Mov AL, 2 + Add DL, 2 + + Mov AH, [SI+18h] ; 16 bit? + Add AH, AH + Or AL, AH + + Out DX, AL + Call GUSDelay + Out DX, AL + Sub DL, 2 + + Xor BX, BX + Call SetGUSVolume + +SetGUSRegisters14: + Test CL, 1 + JZ SetGUSRegisters13 + + Xor CX, CX ; Turn off channel + Test Byte Ptr [SI+3Ah], 80h + JNZ SetGUSRegisters13 + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Signify channel off + + Jmp SetGUSRegisters13 + +SetGUSRegisters12: ; Turn on + Xor AL, AL + Out DX, AL + + Mov AL, [SI+0Ah] + + Cmp CS:Convert16To8Bit, 0 + JNZ SetGUSRegistersNo16Bit + + Mov AH, [SI+18h] ; 16 bit? + Add AH, AH + Or AL, AH + +SetGUSRegistersNo16Bit: + Test CL, 1 + JNZ SetGUSRegisters15 + + Mov AL, 2 + Xor CX, CX + +SetGUSRegisters15: + Add DL, 2 + Out DX, AL + Call GUSDelay + Out DX, AL + +SetGUSRegisters13: + And CX, 0111100010011111b ; Turns off: + ; 1) Freq, pan & vol recalc + ; 2) New note/note stop/loop cha + + Mov [SI], CX + + Add SI, SLAVECHANNELSIZE + +; Call CheckMIDI + + Pop CX + Pop AX + + Inc AX + Dec CX + JNZ SetGUSRegisters1 + + Ret + + +EndP SetGUSRegisters + diff --git a/SoundDrivers/GUSPNPM.ASM b/SoundDrivers/GUSPNPM.ASM new file mode 100755 index 0000000..a2c9d5d --- /dev/null +++ b/SoundDrivers/GUSPNPM.ASM @@ -0,0 +1,2270 @@ +; +; Windows Sound System Driver, with GUS PnP detection. +; + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;********************************** + +STEREOENABLED EQU 1 +DMABUFFERLENGTH EQU 8192 +MIXRESOLUTION EQU 32 ; 32 bit mixing for +MIXTABLESIZE EQU 2*256*65 + +PNPVENDORID EQU 0100561Eh + +DMASize DW 2048 + +WSSMsg DB "Gravis UltraSound PnP Codec", 13 + DB "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, DMA ", 0FDh, "D", 0 + +WSSNoMemoryMsg DB "Gravis UltraSound PnP Codec", 13 + DB "Error: Insufficient memory", 0 + +ReinitMsg DB "Gravis UltraSound PnP Codec reinitialised", 0 + +DriverName DB "ITGUSPNP.DRV", 0 + +Forced DB 0 +Stereo DB 0 +MixVolume DW 0 + +BytesToMix DW 1000 +WSSMixConst DB 0 + +MixSegment DW 0 +DMASegment DW 0 + +MixTransferOffset DW 0 +MixTransferRemaining DW 0 + +CONFIGURATIONOFFSET EQU $+128 +CONFIGSIZE EQU 6 +MixMode DW 0 +MixModeOffset DW 0 +Filter DW 0 + +IMR DW 0 +OldWSSIRQHandler DD 0 + +FilterValue DD 0 +FilterValue2 DD 0 + +MixSpeedTable DW 5513, 41h + DW 6615, 4Fh + DW 8000, 40h + DW 9600, 4Eh + DW 11025, 43h + DW 16000, 42h + DW 18900, 45h + DW 22050, 47h + DW 27429, 44h + DW 32000, 46h + DW 33075, 4Dh + DW 37800, 49h + DW 44100, 4Bh + DW 48000, 4Ch + DW 54860, 48h + DW 64000, 4Ah + +IRQData Label Word + DW 20h, 1111111111111110b ; IRQ 0 + DW 24h, 1111111111111101b ; IRQ 1 + DW 28h, 1111110111111011b ; IRQ 2 + DW 2Ch, 1111111111110111b ; IRQ 3 + DW 30h, 1111111111101111b ; IRQ 4 + DW 34h, 1111111111011111b ; IRQ 5 + DW 38h, 1111111110111111b ; IRQ 6 + DW 3Ch, 1111111101111111b ; IRQ 7 + DW 1C0h, 1111111011111011b ; IRQ 8 + DW 1C4h, 1111110111111011b ; IRQ 9 + DW 1C8h, 1111101111111011b ; IRQ 10 + DW 1CCh, 1111011111111011b ; IRQ 11 + DW 1D0h, 1110111111111011b ; IRQ 12 + DW 1D4h, 1101111111111011b ; IRQ 13 + DW 1D8h, 1011111111111011b ; IRQ 14 + DW 1DCh, 0111111111111011b ; IRQ 15 + +;********************************** +; WSS Registers +;********************************** + +CODEC_INDEX_LIC = 00 +CODEC_INDEX_RIC = 01h +CODEC_INDEX_LX1C = 02h +CODEC_INDEX_RX1C = 03h +CODEC_INDEX_LX2C = 04h +CODEC_INDEX_RX2C = 05h +CODEC_INDEX_LDC = 06h +CODEC_INDEX_RDC = 07h +CODEC_INDEX_CDF = 08h +CODEC_INDEX_INTF = 09h +CODEC_INDEX_PIN = 0Ah +CODEC_INDEX_TEST = 0Bh +CODEC_INDEX_MISC = 0Ch +CODEC_INDEX_DIGMIX = 0Dh +CODEC_INDEX_UPR_COUNT = 0Eh +CODEC_INDEX_LWR_COUNT = 0Fh + +CODEC_MCE = 40h + +LDC_LDM = 80h +LDC_LDA = 3Fh + +RDC_RDM = 80h +RDC_RDA = 3Fh + +CDF_STEREO = 10h + +INTF_PEN = 01h +INTF_CEN = 02h +INTF_SDC = 04h +INTF_ACAL = 08h +INTF_PPIO = 40h +INTF_CPIO = 80h + +PIN_IEN = 2 + +TEST_ORL = 03h +TEST_ORR = 0Ch +TEST_DRS = 10h +TEST_ACI = 20h +TEST_PUR = 40h +TEST_COR = 80h + +;********************************** + +WSS16ScreenList Label + DW 16 + DW Near Ptr IdleFunctionList + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr WSSHeaderLine + + DW Near Ptr DriverText + + DW Near Ptr MixModeText + DW Near Ptr MixModeButton1 ; 6 + DW Near Ptr MixModeButton2 ; + DW Near Ptr MixModeButton3 ; 8 + DW Near Ptr MixModeButton4 ; 9 + + DW Near Ptr FilterText + DW Near Ptr FilterButton1 ; 11 + DW Near Ptr FilterButton2 + DW Near Ptr FilterButton3 + + DW Near Ptr VolumeText + DW Near Ptr VolumeBox1 + + DW Near Ptr MasterVolumeLeft ; 16 + DW Near Ptr MasterVolumeRight ; 17 + + DW 0 + +WSSHeaderLine DW 10 + DB "Gravis UltraSound PnP Codec Driver", 0 + +EmptyObject DW 1 + DB 0, 0 + DB 0 + DB 0 + +DriverText DW 1 + DB 19, 48 + DB 21h + DB "Gravis UltraSound PnP Codec Driver 1.0 for Impulse Tracker", 0 + +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +IdleFunctionList DD 0 + DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +VolumeText DW 1 + DB 2, 14 + DB 20h + DB "Master Volume Left", 13 + DB "Master Volume Right" + DB 0 + +VolumeBox1 DW 0 + DB 21, 13, 31, 16 + DB 25 + +MasterVolumeLeft DW 9 + DB 22, 14 + DW 0, 63 + DW 9, 0 + DW 0FFFFh, 17, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +MasterVolumeRight DW 9 + DB 22, 15 + DW 0, 63 + DW 9, 1 + DW 16, 6, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +MixModeText DW 1 + DB 2, 18 + DB 20h + DB "Mixing Mode, Playback Frequency: ", 0FDh, "DHz", 0 +MixSpeed DW 48000 + +MixModeButton1 DW 2 + DW 17, 7, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment1 DW 0 + DW 0 + DW Offset SetMixMode +DriverSegment2 DW 0 + DB 3, 20, 32, 22, 8 + DB 0 + DB " 16 Bit, Non-Interpolated", 0 + +MixModeButton2 DW 2 + DW 6, 8, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment3 DW 0 + DW 2 + DW Offset SetMixMode +DriverSegment4 DW 0 + DB 3, 23, 32, 25, 8 + DB 0 + DB " 16 Bit, Interpolated", 0 + +MixModeButton3 DW 2 + DW 7, 9, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment5 DW 0 + DW 4 + DW Offset SetMixMode +DriverSegment6 DW 0 + DB 3, 26, 32, 28, 8 + DB 0 + DB " 32 Bit, Non-Interpolated", 0 + +MixModeButton4 DW 2 + DW 8, 11, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment7 DW 0 + DW 6 + DW Offset SetMixMode +DriverSegment8 DW 0 + DB 3, 29, 32, 31, 8 + DB 0 + DB " 32 Bit, Interpolated", 0 + +FilterText DW 1 + DB 2, 33 + DB 20h + DB "Filter mode", 0 + +FilterButton1 DW 2 + DW 9, 12, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment9 DW 0 + DW 0 + DW Offset SetFilter +DriverSegment10 DW 0 + DB 3, 35, 29, 37, 8 + DB 0 + DB " No Filter", 0 + +FilterButton2 DW 2 + DW 11, 13, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment11 DW 0 + DW 1 + DW Offset SetFilter +DriverSegment12 DW 0 + DB 3, 38, 29, 40, 8 + DB 0 + DB " 50% Filter", 0 + +FilterButton3 DW 2 + DW 12, 0FFFFh, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment13 DW 0 + DW 2 + DW Offset SetFilter +DriverSegment14 DW 0 + DB 3, 41, 29, 43, 8 + DB 0 + DB " 75% Filter", 0 + +VolumeTable DB 2 Dup (56) + +; ÄÄ MixingRoutines ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixBufferPos DW 0 + +include dma.inc +include mix.inc +include m12bit.mix +include m12biti.mix +include m32bit.mix +include m32biti.mix + +MixFunctionTables Label + +include m12bit.inc ; contains the tables +include m12biti.inc +include m32bit.inc +include m32biti.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +RelocationTable Label Word + DW Offset DriverSegment1, Offset DriverSegment2 + DW Offset DriverSegment3, Offset DriverSegment4 + DW Offset DriverSegment5, Offset DriverSegment6 + DW Offset DriverSegment7, Offset DriverSegment8 + DW Offset DriverSegment9, Offset DriverSegment10 + DW Offset DriverSegment11, Offset DriverSegment12 + DW Offset DriverSegment13, Offset DriverSegment14 + DW 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixMode Far + + Push CS + Pop ES + Mov DI, Offset MixMode + + Ret + +EndP GetMixMode + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetFilter Far + + Push CS + Pop ES + Mov DI, Offset Filter + + Ret + +EndP GetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetFilter Far + + Mov AX, [SI+22] + Mov CS:FilterValue, 0 + Mov CS:Filter, AX + + Mov AX, 1 + Ret + +EndP SetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WaitCoDec + + Push CX + + Mov CX, 0F000h + +WaitCoDec1: + In AL, DX + Test AL, AL + JNS WaitCoDec2 + Loop WaitCoDec1 + + StC + +WaitCoDec2: + Pop CX + Ret + +EndP WaitCoDec + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WaitAutoCalibration + + Push CX + Mov CX, 0F000h + +WaitAutoCalibration1: + Mov AL, CODEC_INDEX_TEST + Out DX, AL + Inc DX + In AL, DX + Dec DX + Test AL, TEST_ACI + JNZ WaitAutoCalibration2 + Loop WaitAutoCalibration1 + + StC + +WaitAutoCalibration2: + Pop CX + Ret + +EndP WaitAutoCalibration + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixMode Far + + Mov AX, [SI+22] + + ClI + + Mov CS:MixMode, AX + + Mov BX, 180 + Mul BX + Mov CS:MixModeOffset, AX + + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS:RecalculateAllVolumes + + StI + + Mov AX, 1 + Ret + +EndP SetMixMode + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetWSSMixConst ; Work out value.. and nearest + ; mixspeed value. + + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, CmdLineMixSpeed + Mov CX, MixSpeed + Test AX, AX + JZ GetWSSMixConst1 + + Mov CX, 64000 + Cmp AX, CX + JA GetWSSMixConst1 + + Mov CX, 8000 + Cmp AX, CX + JB GetWSSMixConst1 + + Mov CX, AX + +GetWSSMixConst1: ; CX = desired mixspeed + Mov SI, Offset MixSpeedTable + Mov DX, 16 ; 14 different available speeds + + Xor BX, BX + +GetWSSMixConst2: + LodsW + Cmp AX, BX + JB GetWSSMixConst3 + Cmp AX, CX + JA GetWSSMixConst3 + + Mov BX, AX + Mov DH, [SI] + +GetWSSMixConst3: + LodsW ; Add SI, 2 + Dec DL + JNZ GetWSSMixConst2 + + Mov MixSpeed, BX + Mov WSSMixConst, DH + + Pop DS + PopA + Ret + +EndP GetWSSMixConst + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PingWSS ; Check BasePort, DX = BasePort + ; Preserves DX, destroys AX + + Push DX + + Inc DX + Inc DX + + In AL, DX + Xor AL, AL + Out DX, AL + + Dec DX + Dec DX + Call WaitCodec + JC PingWSSFailure + + In AL, DX + Test AL, AL + JS PingWSSFailure + + Mov AL, CODEC_INDEX_MISC + Out DX, AL + Inc DX ; DX = Data port + In AL, DX + Mov AH, AL ; AH = Revision + + Xor AL, AL ; Write 0 revision + Out DX, AL + In AL, DX + And AX, 8F8Fh + Cmp AL, AH + JNE PingWSSFailure + Dec DX ; DX = AD1848 baseport + + Mov AL, CODEC_MCE or CODEC_INDEX_INTF + Out DX, AL + Inc DX + Mov AL, INTF_ACAL or INTF_SDC + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_INTF + Out DX, AL + Inc DX + Mov AL, INTF_ACAL or INTF_SDC + Out DX, AL + Dec DX + + Call WaitAutoCalibration ; Returns carry if error + ; Carry clear if none. + +; JC PingWSSFailure + + Pop DX + Ret + +PingWSSFailure: + Pop DX + + StC + Ret + + +EndP PingWSS + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +PnP_SerialID DD 0 +PnP_VendorID DD 0 +PnP_ReadPort DW 0 +PnP_CSN DB 0 +PnP_CardFound DB 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_Delay + Assume DS:Driver + + Push AX CX + + Mov CX, 180h +PnP_Delay1: + In AL, 21h + Loop PnP_Delay1 + + Pop CX AX + Ret + +EndP PnP_Delay + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_WriteData + + Mov DX, 279h + Out DX, AL + + Mov AL, AH + Mov DH, 0Ah + Out DX, AL + Ret + +EndP PnP_WriteData + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_ReadData + + Mov DX, 279h + Out DX, AL + + Mov DX, PnP_ReadPort + In AL, DX + + Ret + +EndP PnP_ReadData + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_Isolate + + Mov AX, 402h + Call Pnp_WriteData ; Reset CSNs + +PnP_IsolateNextCard: + Mov AX, 0003h + Call PnP_WriteData ; Wake[0] + + Mov AX, PnP_ReadPort + ShL AX, 6 + Xor AL, AL + Call PnP_WriteData ; Set Read Data port. + + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + + Mov AL, 1 ; Serial Isolation + Mov DX, 279h + Out DX, AL + + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + + Mov BL, 6Ah + Mov CX, 64 + Mov DX, PnP_ReadPort + + ClI + +PnP_Isolate1: + ShR PnP_SerialID, 1 + RCR PnP_VendorID, 1 + + Mov BH, BL + ShR BH, 1 + Xor BH, BL + ShR BX, 1 + + In AL, DX + Mov AH, AL + Call PnP_Delay + In AL, DX + Call PnP_Delay + + Cmp AX, 55AAh + JNE PnP_Isolate2 + + Xor BL, 80h + Or PnP_SerialID, 80000000h + +PnP_Isolate2: + Dec CX + JNZ PnP_Isolate1 + + Mov CX, 8 + Xor BH, BH + +PnP_Isolate3: + ShR BH, 1 + + In AL, DX + Mov AH, AL + Call PnP_Delay + In AL, DX + Call PnP_Delay + Cmp AX, 55AAh + JNE PnP_Isolate4 + + Or BH, 80h + +PnP_Isolate4: + Dec CX + JNZ PnP_Isolate3 + + StI + + Cmp BL, BH ; Matching Checksum? + JNE PnP_IsolateFinished + + ; assign CSN + Inc PnP_CSN + + Mov AL, 6 + MOv AH, PnP_CSN + Call PnP_WriteData + + Cmp PnP_VendorID, PNPVENDORID + JNE PnP_IsolateNextCard +; Cmp PnP_SerialID, PNPSERIALID +; JNE PnP_IsolateNextCard + + Mov AL, 3 + Call PnP_WriteData + + Mov AX, 07h ; Configuration device + Call PnP_WriteData + + Mov AL, 64h + Call PnP_ReadData + Mov AH, AL + Mov AL, 65h + Call PnP_ReadData ; AX = address. + + Test AX, AX + JZ PnP_IsolateNextCard + + Cmp BasePort, 0FFFFh + JE PnPBasePortOK + + Cmp BasePort, AX + JNE PnP_IsolateNextCard + +PnPBasePortOK: + Mov BasePort, AX + + Mov AL, 70h + Call PnP_ReadData ; AL[3:0] = IRQ + And AX, 15 + JZ PnP_IsolateNextCard + Mov IRQ, AX + + Mov AL, 75h + Call PnP_ReadData ; AL[2:0] = DMA + And AX, 7 + Cmp AL, 4 + JE PnP_IsolateNextCard + Mov DMA, AX + + Mov Pnp_CardFound, 1 + Jmp PnP_IsolateNextCard + +PnP_IsolateFinished: + Mov AL, PnP_CSN + ShL AL, 1 + Or AL, PnP_CardFound + + Ret + +EndP PnP_Isolate + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far ; returns carry clear if succesful + + Push CS + Pop DS + + Xor AL, AL + Mov DX, 279h + Out DX, AL + Out DX, AL + + Mov AL, 6Ah ; Starting value + Mov CX, 32 + +PnP_InitiationKeyLoop: + Out DX, AL + + Mov AH, AL + ShR AH, 1 + Xor AH, AL + ShR AX, 1 + + Dec CX + JNZ PnP_InitiationKeyLoop + +; Try three ports before concluding no PnP cards: 20Fh, 27Bh, 213h + +PnP_DetectCardPort1: + Mov PnP_ReadPort, 20Fh + Call PnP_Isolate + JZ PnP_DetectCardPort2 + Test AL, 1 + JZ PnP_DetectCardNotFound + Jmp PnP_DetectCardFound + +PnP_DetectCardPort2: + Mov PnP_ReadPort, 27Bh + Call PnP_Isolate + JZ PnP_DetectCardPort3 + Test AL, 1 + JZ PnP_DetectCardNotFound + Jmp PnP_DetectCardFound + +PnP_DetectCardPort3: + Mov PnP_ReadPort, 213h + Call PnP_Isolate + Test AL, 1 + JNZ PnP_DetectCardFound + +PnP_DetectCardNotFound: + StC + Mov AX, 202h + Call PnP_WriteData + Ret + +PnP_DetectCardFound: + ClC + +PnP_DetectEnd: ; Return PnP to wait for key state + Mov AX, 202h + Call PnP_WriteData + + Mov EAX, 'Jeff' + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixModeTable Label Word + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + +Proc MixSamples ; Given DS:SI = info tables, CX = numchannels + + ; 1. Clean buffer + ; + update variables + ; 2. Update parameters + ; 3. Mix func + ; 4. Return + + Push CX + + Mov CX, BytesToMix + Mov ES, MixSegment + Mov DI, MIXTABLESIZE + Xor EAX, EAX + Mov DX, CX + Add CX, CX + + Mov MixTransferOffset, DI ; } Memory write + + Cmp Stereo, 0 + JE MixSamples1 + + Mov DX, CX + +MixSamples1: + Rep StosD ; } Memory write + Mov MixTransferRemaining, DX ; } + + Pop CX + +MixSamples2: + Test Byte Ptr [SI], 1 + JZ MixSamplesEnd2 + Cmp Byte Ptr [SI+36h], 100 + JE MixSamplesEnd2 + + Push CX + Mov CX, [SI] + + Test CH, 2 + JZ MixSamples3 + And Byte Ptr [SI], Not 1 + + Jmp MixSamplesEnd +; Cmp MixMode, 8 ; Is it volume ramping? +; JB MixSamplesEnd + +MixSamples3: + Test CL, 20h ; New freq? + JZ MixSamples5 + + Mov AX, [SI+10h] + Mov DX, [SI+12h] + Mov BX, MixSpeed + Cmp DX, BX + JAE MixSamplesHandleError + + Div BX + ShL EAX, 16 + Xor AX, AX + Div BX + Mov STEPVALUE, EAX + +MixSamples4: + Test CH, 1 + JZ MixSamples5 + + Mov DWord Ptr [SI+1Ch], 0 ; Current Volume = 0 + ; for volume sliding. +MixSamples5: + Test CX, 8440h ; New volume or panning? + JZ MixSamplesMix + + Xor AX, AX + Test CH, 8 ; Muted? + JNZ MixModeCommon + + Mov BX, MixMode + Add BL, Stereo + Add BX, BX + Jmp [CS:MixModeTable+BX] + +Mix0Mode: ; 16-bit mixing, no interpolation +Mix0ModeMono: ; and 16-bit mixing, interpolation + Mov AL, [SI+20h] + ShR AL, 1 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 30 ; Use left only-mixing for mono + Jmp MixModeCommon + +Mix0ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix0ModeSurround + + Mul Byte Ptr [SI+20h] ; Final volume + Add AX, 64 + ShR AX, 7 + Mov [SI+0Ch], AX ; Store into right volume + + Mov AL, 64 + Sub AL, [SI+37h] + Mul Byte Ptr [SI+20h] + Add AX, 64 + ShR AX, 7 + Mov [SI+0Eh], AX ; Left volume + + Mov CH, AL ; CH = left volume + Mov CL, [SI+0Ch] ; CL = right volume + Mov AX, 0 + + Test CX, CX + JZ MixModeCommon + + Mov AL, 30 ; Left only... + Test CL, CL + JZ MixModeCommon + + Mov AL, 60 + Test CH, CH + JZ MixModeCommon + + Mov AL, 90 + Cmp CL, CH + JZ MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix0ModeSurround: + Mov AL, [SI+20h] + ShR AL, 2 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 150 ; Surround + Jmp MixModeCommon + +Mix6ModeMono: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 8 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Test AX, AX + JZ MixModeCommon + Mov AX, 30 + Jmp MixModeCommon + +Mix6ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix6ModeSurround + + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Ch], AX ; Store into right volume + Mov BX, AX + ShL EAX, 16 + + Mov AL, 64 ; Do left volume + Sub AL, [SI+37h] ; AL = 64-FinalPan + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Eh], AX + + Mov ECX, EAX + + ; BX = right volume + ; CX = Left volume + Mov AX, 0 + Test ECX, ECX + JZ MixModeCommon + + Mov AL, 30 + Test BX, BX + JZ MixModeCommon + + Mov AL, 60 + Test CX, CX + JZ MixModeCommon + + Mov AL, 90 + Cmp CX, BX + JE MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix6ModeSurround: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 9 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + JZ MixModeCommon + Mov AX, 150 + Jmp MixModeCommon + +MixModeCommon: ; Requires AX = 30/60/90 etc. depending + ; On mixing mode type. + ; This will add 180 for 16-bit, + ; And sort out loop types. + Mov BL, [SI+0Ah] + Test Byte Ptr [SI+18h], 2 ; 16 bit? + JZ MixModeCommon1 + + Add AX, 180 + +MixModeCommon1: + Cmp BL, 8 + JB MixModeCommon3 ; No loop + JE MixModeCommon2 ; Forwards loop + + Add AX, 10 + +MixModeCommon2: + Add AX, 10 + +MixModeCommon3: + Add AX, Offset MixFunctionTables + Add AX, MixModeOffset + Mov [SI+8], AX ; Offset... + +MixSamplesMix: + Mov BX, [SI+8] ; BX = offset into + Mov EAX, [CS:BX+2] + Mov DWord Ptr PreMixFunction, EAX + Mov EAX, [CS:BX+6] + Mov DWord Ptr MixFunctionSeparateBackwards, EAX + + Mov AX, BytesToMix + Mov MixBlockSize, AX + Mov MixBufferOffset, MIXTABLESIZE + + Mov EAX, CURRENTPOSITION + Mov OLDPOSITION, EAX + + Call Word Ptr [CS:BX] + + And Word Ptr [SI], 0111100010001101b + Jmp MixSamplesEnd + +MixSamplesHandleError: + Mov Word Ptr [SI], 200h + + Test Byte Ptr [SI+3Ah], 80h + JNZ MixSamplesEnd + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Turn off channel + +MixSamplesEnd: + Pop CX + +MixSamplesEnd2: + Add SI, 128 + Dec CX + JNZ MixSamples2 + + Ret + +EndP MixSamples + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WSSIRQHandler + + PushAD + Push DS + Push ES + + ClD + + Mov AX, CS + Mov DS, AX + Assume DS:Driver + + Mov DX, [BasePort] + Add DX, 2 + In AL, DX + Test AL, 1 + JZ WSSAckIRQ2 + + Xor AL, AL + Out DX, AL + +WSSAckIRQ2: + Mov AL, 20h + Cmp IRQ, 8 + JB WSSAckIRQ1 + + Out 0A0h, AL + +WSSAckIRQ1: + Out 20h, AL + + Mov AX, MixBufferPos + Mov BX, AX + Mul DMASize + Cmp AX, DMABUFFERLENGTH + JB WSSIRQHandler2 + + Xor AX, AX + Xor BX, BX + +WSSIRQHandler2: + Inc BX + Mov MixBufferPos, BX + + CLD + + ; OK... time to get next block + ; Check whether stereo thing is on.. + ; + LES DI, [ActualDMAPtr] + Add DI, AX + + Mov BX, DMASize ; BX = bytes required + ShR BX, 1 + ; BX = samples required + Mov BP, 8 ; Skip for mono + Mov CL, 14 ; Shift for mono + + Cmp Stereo, 0 + JE WSSIRQHandlerMono + + Mov BP, 4 ; Stereo skip value. + Dec CL + +WSSIRQHandlerMono: + Call SaveEMSPageFrame + + Cmp MixTransferRemaining, 0 + JNE WSSIRQHandler4 + Assume DS:Nothing + +WSSIRQHandler3: + Push BX + Push CX + Push BP + Push ES + Push DI + + Call Update + Call MixSamples + + Pop DI + Pop ES + Pop BP + Pop CX + Pop BX + +WSSIRQHandler4: + Mov DS, MixSegment + Mov SI, MixTransferOffset + Mov DX, BX ; DX = samples to transfer + Cmp DX, MixTransferRemaining + JBE WSSIRQHandler5 + + Mov DX, MixTransferRemaining + +WSSIRQHandler5: + Push DX + Cmp CS:Filter, 1 + JB WSSIRQHandler6 + JE WSSIRQHFilter + + Cmp CS:Stereo, 0 + JE WSSIRQ3QFilterMono + +WSSIRQ3QFilterStereo: + Push BX + + Mov EBX, FilterValue + Mov EBP, FilterValue2 + ShR DX, 1 + +WSSIRQ3QFilterStereo1: + Mov EAX, EBX + Mov ECX, EBP + Add EAX, [SI] + Add ECX, [SI+4] + SAR EAX, 1 + SAR ECX, 1 + Add EBX, EAX + Add EBP, ECX + SAR EBX, 1 + SAR EBP, 1 + + Mov EAX, EBX + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSS3QFilterStereoClip1 + Cmp EAX, 7FFFh + JG WSS3QFilterStereoClip2 + +WSSIRQ3QFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSS3QFilterStereoClip3 + Cmp EAX, 7FFFh + JG WSS3QFilterStereoClip4 + +WSSIRQ3QFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ WSSIRQ3QFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp WSSMixTransferEnd + +WSSIRQ3QFilterMono: + Push BX + + Mov EBX, FilterValue + +WSSIRQ3QFilterMono1: + Mov EAX, EBX + Add EAX, [SI] + SAR EAX, 1 + Add EBX, EAX + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL WSS3QFilterMonoClip1 + Cmp EAX, 7FFFh + JG WSS3QFilterMonoClip2 + +WSSIRQ3QFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ WSSIRQ3QFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp WSSMixTransferEnd + +WSSIRQHFilter: + Cmp CS:Stereo, 0 + JE WSSIRQHFilterMono + +WSSIRQHFilterStereo: + Push BX + + Mov EBX, FilterValue + Mov EBP, FilterValue2 + ShR DX, 1 + +WSSIRQHFilterStereo1: + Add EBX, [SI] + Add EBP, [SI+4] + + SAR EBX, 1 + SAR EBP, 1 + + Mov EAX, EBX + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSSHFilterStereoClip1 + Cmp EAX, 7FFFh + JG WSSHFilterStereoClip2 + +WSSIRQHFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSSHFilterStereoClip3 + Cmp EAX, 7FFFh + JG WSSHFilterStereoClip4 + +WSSIRQHFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ WSSIRQHFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp WSSMixTransferEnd + +WSSIRQHFilterMono: + Push BX + + Mov EBX, FilterValue + +WSSIRQHFilterMono1: + Add EBX, [SI] + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL WSSHFilterMonoClip1 + Cmp EAX, 7FFFh + JG WSSHFilterMonoClip2 + +WSSIRQHFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ WSSIRQHFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp WSSMixTransferEnd + +WSSIRQHandler6: + Mov EAX, [SI] + SAR EAX, CL + + Cmp EAX, -8000h + JL WSSIRQHandlerClip1 + Cmp EAX, 7FFFh + JG WSSIRQHandlerClip2 + +WSSIRQHandler7: + StosW ; } Memory write + + Add SI, BP + Dec DX + JNZ WSSIRQHandler6 + +WSSMixTransferEnd: + Pop DX + + Sub MixTransferRemaining, DX ; } Memory write + Sub BX, DX + JNZ WSSIRQHandler3 + + Mov MixTransferOffset, SI ; } Memory write + + Call RestoreEMSPageFrame + + Pop ES + Pop DS + PopAD + IRet + +WSSIRQHandlerClip1: + Mov AX, 8000h + Jmp WSSIRQHandler7 + +WSSIRQHandlerClip2: + Mov AX, 7FFFh + Jmp WSSIRQHandler7 + +WSSHFilterMonoClip1: + Mov AX, 8000h + Jmp WSSIRQHFilterMono2 + +WSSHFilterMonoClip2: + Mov AX, 7FFFh + Jmp WSSIRQHFilterMono2 + +WSSHFilterStereoClip1: + Mov AX, 8000h + Jmp WSSIRQHFilterStereo2 + +WSSHFilterStereoClip2: + Mov AX, 7FFFh + Jmp WSSIRQHFilterStereo2 + +WSSHFilterStereoClip3: + Mov AX, 8000h + Jmp WSSIRQHFilterStereo3 + +WSSHFilterStereoClip4: + Mov AX, 7FFFh + Jmp WSSIRQHFilterStereo3 + +WSS3QFilterMonoClip1: + Mov AX, 8000h + Jmp WSSIRQ3QFilterMono2 + +WSS3QFilterMonoClip2: + Mov AX, 7FFFh + Jmp WSSIRQ3QFilterMono2 + +WSS3QFilterStereoClip1: + Mov AX, 8000h + Jmp WSSIRQ3QFilterStereo2 + +WSS3QFilterStereoClip2: + Mov AX, 7FFFh + Jmp WSSIRQ3QFilterStereo2 + +WSS3QFilterStereoClip3: + Mov AX, 8000h + Jmp WSSIRQ3QFilterStereo3 + +WSS3QFilterStereoClip4: + Mov AX, 7FFFh + Jmp WSSIRQ3QFilterStereo3 + +EndP WSSIRQHandler + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Add DI, Offset IRQData + Mov BX, [CS:DI] + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset WSSIRQHandler + + XChg [ES:BX], EAX + Mov OldWSSIRQHandler, EAX + + Mov AX, IMR + And AX, [DI+2] + + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Pop ES + PopAD + + Ret + +EndP SetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Mov BX, [IRQData+DI] + + Mov EAX, OldWSSIRQHandler + Mov [ES:BX], EAX + + Pop ES + PopAD + + Ret + +EndP ResetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StopWSS + + Mov DX, BasePort + + Mov AL, CODEC_INDEX_INTF + Out DX, AL + Inc DX + In AL, DX + And AL, Not INTF_PEN + Out DX, AL + + Inc DX + In AL, DX + Xor AL, AL + Out DX, AL + + Dec DX + Dec DX + + Mov AL, CODEC_INDEX_PIN + Out DX, AL + Inc DX + Xor AL, AL + Out DX, AL + + Ret + +EndP StopWSS + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StartWSS + + PushA + Push ES + Push DS + + Push CS + Pop DS + Assume DS:Driver + + ; Setup DMA + Mov BX, DMASegment + Xor AX, AX + Mov DX, DMA + Mov DI, DMABUFFERLENGTH + Call SetDMA + + LES DI, ActualDMAPtr + Xor AX, AX + Mov CX, DMABUFFERLENGTH/2 + Rep StosW + + Mov MixBufferPos, 0 + Mov MixTransferRemaining, 0 + + Mov DX, BasePort + Call PingWSS + + Mov AL, CODEC_INDEX_PIN + Out DX, AL + Inc DX + Mov AL, PIN_IEN + Out DX, AL + Dec DX + + Mov AH, WSSMixConst ; Set format/frequency + Cmp Stereo, 0 + JE StartWSS1 + + Or AH, CDF_STEREO + +StartWSS1: + Mov AL, CODEC_MCE or CODEC_INDEX_CDF + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Call WaitCodec + + Mov AL, CODEC_INDEX_CDF + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Call WaitAutoCalibration + + ; Start playback + Mov AL, CODEC_INDEX_LWR_COUNT + Out DX, AL + Inc DX + + Mov AX, DMASize + ShR AX, 1 + + Cmp Stereo, 0 + JE StartWSS2 + + ShR AX, 1 + +StartWSS2: + Dec AX + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_UPR_COUNT + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_INTF + Out DX, AL + Inc DX + In AL, DX + Or AL, INTF_PEN + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_LDC + Out DX, AL + Inc DX + In AL, DX + And AL, Not LDC_LDM + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_RDC + Out DX, AL + Inc DX + In AL, DX + And AL, Not RDC_RDM + Out DX, AL + Dec DX + + Pop DS + Pop ES + PopA + + Ret + +EndP StartWSS + Assume DS:Nothing + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov SI, Offset RelocationTable + +RelocationFix: + LodsW + Test AX, AX + JZ RelocationEnd + Mov BX, AX + Mov [BX], DS + Jmp RelocationFix + + +RelocationEnd: + Call GetEMSPageFrame + Mov EMSPageFrame, AX + + In AL, 0A1h + Mov AH, AL + In AL, 21h + Mov IMR, AX + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + Call GetWSSMixConst + + Mov AX, 2643 + Mul MixSpeed + Add AX, 0FFFFh + AdC DX, 2080 + + Mov BX, (DMABUFFERLENGTH*2)/16 + Add BX, DX + + ; Allocate MixSegment first + Mov AH, 48h + + Int 21h + JNC InitSound1 + +InitSoundNoMemory: + Mov SI, Offset WSSNoMemoryMsg + Ret + +InitSound1: + Mov MixSegment, AX + Add AX, DX + Mov DMASegment, AX + + Call SetIRQ + Call GetTempo + Call SetTempo + + Call UpdateSoundcardVariables + + Mov SI, Offset WSSMsg + + Mov AX, BasePort + Mov BX, IRQ + Mov CX, DMA + + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Call ResetIRQ + Call SetIRQ + + Mov SI, Offset ReInitMsg + Mov BX, 40 + Call SetInfoLine + + Mov AL, Stereo + Call SetStereo + + Pop ES + Pop DS + PopA + + Ret + +EndP ReInitSound + Assume DS:Nothing + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, IMR + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Mov AX, MixSegment + Test AX, AX + JZ UnInitSound1 + + Mov ES, AX + Mov AH, 49h ; Release MixSegment + Int 21h + + Call StopWSS + Call ResetIRQ + +UnInitSound1: + Call GotoHomeDirectory + + ; Now to save config into driver file. + Mov AX, 3D02h ; Read write access + Mov DX, Offset DriverName + Int 21h + JC SetMixMode1 + + Mov BX, AX + + Mov AX, 4200h + Xor CX, CX + Mov DX, Offset CONFIGURATIONOFFSET + Int 21h + JC SetMixMode2 + + Mov AH, 40h + Mov CX, CONFIGSIZE + Mov DX, Offset MixMode + Int 21h + +SetMixMode2: + Mov AH, 3Eh + Int 21h + +SetMixMode1: + Ret + +EndP UnInitSound + Assume DS:Nothing + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + Ret + +EndP Poll + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Push AX + Push BX + Push DX + + Push BX + + Mov AX, MixSpeed + Mov BX, AX + Xor DX, DX + + ShL AX, 1 + RCL DX, 1 ; DX:AX = Mixspeed*2 + + ShR BX, 1 ; BX = Mixspeed/2 + + Add AX, BX + AdC DX, 0 ; DX:AX = Mixspeed*2.5 + + Pop BX ; BX = tempo + Div BX + + Mov BytesToMix, AX + + Pop DX + Pop BX + Pop AX + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + PushA + Push DS + + Mov BX, AX ; BX = MixVolume + Mov CS:MixVolume, BX + + Mov AX, CS:MixSegment + Test AX, AX + JZ SetMixVolume2 + + Mov DS, AX + + Mov CX, MIXTABLESIZE/2 + Mov SI, MIXTABLESIZE-2; Starting point - working backwards + +SetMixVolume1: + Mov AX, CX + + Dec AX ; AH = volume, AL = wave value. + Xor DX, DX + XChg AH, DL ; DL = Volume, AX = wave value + CBW + + IMul DX ; DX:AX = Volume * Wave Value + ; Ranges -8192->8128 + + IMul BX ; DX:AX = Volume * Wave Value * Mixing Volume + ; Ranges -1048576->1040384 + + Add AX, 64 + AdC DX, 0 + + ShRD AX, DX, 7 + Mov [SI], AX + Sub SI, 2 + + Loop SetMixVolume1 + +SetMixVolume2: + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS: RecalculateAllVolumes + + Pop DS + PopA + + Ret + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc RecalculateAllFrequencies + + Call GetChannelTables + +RecalculateAllFrequencies1: + Or Byte Ptr [SI], 32 + + Add SI, 128 + Dec CX + JNZ RecalculateAllFrequencies1 + + Ret + +EndP RecalculateAllFrequencies + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Mov CS:Stereo, AL + Cmp CS:MixSegment, 0 + JE SetStereo1 + + Call StopWSS + Call StartWSS + + Call RecalculateAllFrequencies + +SetStereo1: + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include loadsam.inc + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset WSS16ScreenList + + ClC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far + + Xor AH, AH + Mov AL, [CS:VolumeTable+DI] + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UpdateSoundcardVariables + + Push AX DX + + Push CS + Pop DS + Assume DS:Driver + + Mov DX, BasePort + + Mov AL, CODEC_INDEX_LDC + Out DX, AL + Inc DX + Mov AX, 3F3Fh + Sub AX, [Word Ptr VolumeTable] + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_RDC + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Pop DX AX + Ret + +EndP UpdatesoundcardVariables + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far + + Push DS + Push DX + + Push CS + Pop DS + Assume DS:Driver + + Mov [VolumeTable+DI], AL + Call UpdateSoundcardVariables + + Pop DX + Pop DS + Ret + +EndP SetVariable + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. + +StopAfterPlay DW 0 +DefaultChannels DW 64 + DW 5 Dup (0) + + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/GUSPNPMX.ASM b/SoundDrivers/GUSPNPMX.ASM new file mode 100755 index 0000000..a94e740 --- /dev/null +++ b/SoundDrivers/GUSPNPMX.ASM @@ -0,0 +1,1769 @@ +; +; Windows Sound System Driver, with GUS PnP detection, MMX mixing. +; + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc +include mmx.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;********************************** + +STEREOENABLED EQU 1 +DMABUFFERLENGTH EQU 8192 +MIXRESOLUTION EQU 32 ; 32 bit mixing for +OUTPUTFILTERENABLED EQU 0 + +PNPVENDORID EQU 0100561Eh + +FPSave DB 128 Dup (0) + +DMASize DW 2048 + +WSSMsg DB "Gravis UltraSound PnP MMX", 13 + DB "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, DMA ", 0FDh, "D", 0 + +WSSNoMemoryMsg DB "Gravis UltraSound PnP MMX", 13 + DB "Error: Insufficient memory", 0 + +ReinitMsg DB "Gravis UltraSound PnP Codec reinitialised", 0 + +DriverName DB "ITGUSPNP.MMX", 0 + +Forced DB 0 +Stereo DB 0 +MixVolume DW 0 + +BytesToMix DW 1000 +WSSMixConst DB 0 + +MixSegment DW 0 + +MixTransferOffset DW 0 +MixTransferRemaining DW 0 + +CONFIGURATIONOFFSET EQU $+128 +CONFIGSIZE EQU 6 +MixMode DW 0 +MixModeOffset DW 0 +Filter DW 0 + +IMR DW 0 +OldWSSIRQHandler DD 0 + +MixSpeedTable DW 5513, 41h + DW 6615, 4Fh + DW 8000, 40h + DW 9600, 4Eh + DW 11025, 43h + DW 16000, 42h + DW 18900, 45h + DW 22050, 47h + DW 27429, 44h + DW 32000, 46h + DW 33075, 4Dh + DW 37800, 49h + DW 44100, 4Bh + DW 48000, 4Ch + DW 54860, 48h + DW 64000, 4Ah + +IRQData Label Word + DW 20h, 1111111111111110b ; IRQ 0 + DW 24h, 1111111111111101b ; IRQ 1 + DW 28h, 1111110111111011b ; IRQ 2 + DW 2Ch, 1111111111110111b ; IRQ 3 + DW 30h, 1111111111101111b ; IRQ 4 + DW 34h, 1111111111011111b ; IRQ 5 + DW 38h, 1111111110111111b ; IRQ 6 + DW 3Ch, 1111111101111111b ; IRQ 7 + DW 1C0h, 1111111011111011b ; IRQ 8 + DW 1C4h, 1111110111111011b ; IRQ 9 + DW 1C8h, 1111101111111011b ; IRQ 10 + DW 1CCh, 1111011111111011b ; IRQ 11 + DW 1D0h, 1110111111111011b ; IRQ 12 + DW 1D4h, 1101111111111011b ; IRQ 13 + DW 1D8h, 1011111111111011b ; IRQ 14 + DW 1DCh, 0111111111111011b ; IRQ 15 + +;********************************** +; WSS Registers +;********************************** + +CODEC_INDEX_LIC = 00 +CODEC_INDEX_RIC = 01h +CODEC_INDEX_LX1C = 02h +CODEC_INDEX_RX1C = 03h +CODEC_INDEX_LX2C = 04h +CODEC_INDEX_RX2C = 05h +CODEC_INDEX_LDC = 06h +CODEC_INDEX_RDC = 07h +CODEC_INDEX_CDF = 08h +CODEC_INDEX_INTF = 09h +CODEC_INDEX_PIN = 0Ah +CODEC_INDEX_TEST = 0Bh +CODEC_INDEX_MISC = 0Ch +CODEC_INDEX_DIGMIX = 0Dh +CODEC_INDEX_UPR_COUNT = 0Eh +CODEC_INDEX_LWR_COUNT = 0Fh + +CODEC_MCE = 40h + +LDC_LDM = 80h +LDC_LDA = 3Fh + +RDC_RDM = 80h +RDC_RDA = 3Fh + +CDF_STEREO = 10h + +INTF_PEN = 01h +INTF_CEN = 02h +INTF_SDC = 04h +INTF_ACAL = 08h +INTF_PPIO = 40h +INTF_CPIO = 80h + +PIN_IEN = 2 + +TEST_ORL = 03h +TEST_ORR = 0Ch +TEST_DRS = 10h +TEST_ACI = 20h +TEST_PUR = 40h +TEST_COR = 80h + +;********************************** + +WSS16ScreenList Label + DW 12 + DW Near Ptr IdleFunctionList + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr WSSHeaderLine + + DW Near Ptr DriverText + + DW Near Ptr MixModeText + DW Near Ptr MixModeButton1 ; 6 + DW Near Ptr MixModeButton2 ; + DW Near Ptr MixModeButton3 ; 8 + DW Near Ptr MixModeButton4 ; 9 + + DW Near Ptr VolumeText + DW Near Ptr VolumeBox1 + + DW Near Ptr MasterVolumeLeft ; 12 + DW Near Ptr MasterVolumeRight ; 13 + + DW 0 + + +WSSHeaderLine DW 10 + DB "Gravis UltraSound PnP MMX Codec Driver", 0 + +DriverText DW 1 + DB 19, 48 + DB 21h + DB "Gravis UltraSound PnP Codec Driver 1.0 for Impulse Tracker", 0 + +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +IdleFunctionList DD 0 + DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +VolumeText DW 1 + DB 2, 14 + DB 20h + DB "Master Volume Left", 13 + DB "Master Volume Right" + DB 0 + +VolumeBox1 DW 0 + DB 21, 13, 31, 16 + DB 25 + +MasterVolumeLeft DW 9 + DB 22, 14 + DW 0, 63 + DW 9, 0 + DW 0FFFFh, 13, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +MasterVolumeRight DW 9 + DB 22, 15 + DW 0, 63 + DW 9, 1 + DW 12, 6, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +MixModeText DW 1 + DB 2, 18 + DB 20h + DB "Mixing Mode, Playback Frequency: ", 0FDh, "DHz", 0 +MixSpeed DW 48000 + DW 0 + +MixModeButton1 DW 2 + DW 13, 7, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment1 DW 0 + DW 0 + DW Offset SetMixMode +DriverSegment2 DW 0 + DB 3, 20, 32, 22, 8 + DB 0 + DB " MMX, Non-Interpolated", 0 + +MixModeButton2 DW 2 + DW 6, 8, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment3 DW 0 + DW 1 + DW Offset SetMixMode +DriverSegment4 DW 0 + DB 3, 23, 32, 25, 8 + DB 0 + DB " MMX, Interpolated", 0 + +MixModeButton3 DW 2 + DW 7, 9, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment5 DW 0 + DW 2 + DW Offset SetMixMode +DriverSegment6 DW 0 + DB 3, 26, 32, 28, 8 + DB 0 + DB " MMX, Volume Ramped", 0 + +MixModeButton4 DW 2 + DW 8, 0FFFFh, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment7 DW 0 + DW 3 + DW Offset SetMixMode +DriverSegment8 DW 0 + DB 3, 29, 32, 31, 8 + DB 0 + DB " MMX, Filtered", 0 + +VolumeTable DB 2 Dup (56) + +; ÄÄ MixingRoutines ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixBufferPos DW 0 + +include dma.inc +include mix.inc + +include m32bitm.mix +include m32bitmi.mix +include m32bitmv.mix +include m32bitmf.mix + +ALIGN 2 + +MixFunctionTables Label + +include m32bitm.inc +include m32bitmi.inc +include m32bitmv.inc +include m32bitmf.inc +include mnomix.inc + + +include nodebug.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +RelocationTable Label Word + DW Offset DriverSegment1, Offset DriverSegment2 + DW Offset DriverSegment3, Offset DriverSegment4 + DW Offset DriverSegment5, Offset DriverSegment6 + DW Offset DriverSegment7, Offset DriverSegment8 + DW 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixMode Far + + Push CS + Pop ES + Mov DI, Offset MixMode + + Ret + +EndP GetMixMode + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WaitCoDec + + Push CX + + Mov CX, 0F000h + +WaitCoDec1: + In AL, DX + Test AL, AL + JNS WaitCoDec2 + Loop WaitCoDec1 + + StC + +WaitCoDec2: + Pop CX + Ret + +EndP WaitCoDec + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WaitAutoCalibration + + Push CX + Mov CX, 0F000h + +WaitAutoCalibration1: + Mov AL, CODEC_INDEX_TEST + Out DX, AL + Inc DX + In AL, DX + Dec DX + Test AL, TEST_ACI + JNZ WaitAutoCalibration2 + Loop WaitAutoCalibration1 + + StC + +WaitAutoCalibration2: + Pop CX + Ret + +EndP WaitAutoCalibration + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixMode Far + + Trace "GUSPnP MMX: SetMixMode" + + Mov AX, [SI+22] + + ClI + + Mov CS:MixMode, AX + + Mov BX, 60 + Mul BX + Mov CS:MixModeOffset, AX + + StI + + Mov AX, 1 + Ret + +EndP SetMixMode + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetWSSMixConst ; Work out value.. and nearest + ; mixspeed value. + + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, CmdLineMixSpeed + Mov CX, MixSpeed + Test AX, AX + JZ GetWSSMixConst1 + + Mov CX, 64000 + Cmp AX, CX + JA GetWSSMixConst1 + + Mov CX, 8000 + Cmp AX, CX + JB GetWSSMixConst1 + + Mov CX, AX + +GetWSSMixConst1: ; CX = desired mixspeed + Mov SI, Offset MixSpeedTable + Mov DX, 16 ; 14 different available speeds + + Xor BX, BX + +GetWSSMixConst2: + LodsW + Cmp AX, BX + JB GetWSSMixConst3 + Cmp AX, CX + JA GetWSSMixConst3 + + Mov BX, AX + Mov DH, [SI] + +GetWSSMixConst3: + LodsW ; Add SI, 2 + Dec DL + JNZ GetWSSMixConst2 + + Mov MixSpeed, BX + Mov WSSMixConst, DH + + FNInit + FILd DWord Ptr [MixSpeed] + FMul FreqMultiplier + FStP FreqMultiplier + + Pop DS + PopA + Ret + +EndP GetWSSMixConst + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PingWSS ; Check BasePort, DX = BasePort + ; Preserves DX, destroys AX + + Push DX + + Inc DX + Inc DX + + In AL, DX + Xor AL, AL + Out DX, AL + + Dec DX + Dec DX + Call WaitCodec + JC PingWSSFailure + + In AL, DX + Test AL, AL + JS PingWSSFailure + + Mov AL, CODEC_INDEX_MISC + Out DX, AL + Inc DX ; DX = Data port + In AL, DX + Mov AH, AL ; AH = Revision + + Xor AL, AL ; Write 0 revision + Out DX, AL + In AL, DX + And AX, 8F8Fh + Cmp AL, AH + JNE PingWSSFailure + Dec DX ; DX = AD1848 baseport + + Mov AL, CODEC_MCE or CODEC_INDEX_INTF + Out DX, AL + Inc DX + Mov AL, INTF_ACAL or INTF_SDC + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_INTF + Out DX, AL + Inc DX + Mov AL, INTF_ACAL or INTF_SDC + Out DX, AL + Dec DX + + Call WaitAutoCalibration ; Returns carry if error + ; Carry clear if none. + +; JC PingWSSFailure + + Pop DX + Ret + +PingWSSFailure: + Pop DX + + StC + Ret + + +EndP PingWSS + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +PnP_SerialID DD 0 +PnP_VendorID DD 0 +PnP_ReadPort DW 0 +PnP_CSN DB 0 +PnP_CardFound DB 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_Delay + Assume DS:Driver + + Push AX CX + + Mov CX, 180h +PnP_Delay1: + In AL, 21h + Loop PnP_Delay1 + + Pop CX AX + Ret + +EndP PnP_Delay + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_WriteData + + Mov DX, 279h + Out DX, AL + + Mov AL, AH + Mov DH, 0Ah + Out DX, AL + Ret + +EndP PnP_WriteData + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_ReadData + + Mov DX, 279h + Out DX, AL + + Mov DX, PnP_ReadPort + In AL, DX + + Ret + +EndP PnP_ReadData + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_Isolate + + Mov AX, 402h + Call Pnp_WriteData ; Reset CSNs + +PnP_IsolateNextCard: + Mov AX, 0003h + Call PnP_WriteData ; Wake[0] + + Mov AX, PnP_ReadPort + ShL AX, 6 + Xor AL, AL + Call PnP_WriteData ; Set Read Data port. + + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + + Mov AL, 1 ; Serial Isolation + Mov DX, 279h + Out DX, AL + + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + + Mov BL, 6Ah + Mov CX, 64 + Mov DX, PnP_ReadPort + + ClI + +PnP_Isolate1: + ShR PnP_SerialID, 1 + RCR PnP_VendorID, 1 + + Mov BH, BL + ShR BH, 1 + Xor BH, BL + ShR BX, 1 + + In AL, DX + Mov AH, AL + Call PnP_Delay + In AL, DX + Call PnP_Delay + + Cmp AX, 55AAh + JNE PnP_Isolate2 + + Xor BL, 80h + Or PnP_SerialID, 80000000h + +PnP_Isolate2: + Dec CX + JNZ PnP_Isolate1 + + Mov CX, 8 + Xor BH, BH + +PnP_Isolate3: + ShR BH, 1 + + In AL, DX + Mov AH, AL + Call PnP_Delay + In AL, DX + Call PnP_Delay + Cmp AX, 55AAh + JNE PnP_Isolate4 + + Or BH, 80h + +PnP_Isolate4: + Dec CX + JNZ PnP_Isolate3 + + StI + + Cmp BL, BH ; Matching Checksum? + JNE PnP_IsolateFinished + + ; assign CSN + Inc PnP_CSN + + Mov AL, 6 + MOv AH, PnP_CSN + Call PnP_WriteData + + Cmp PnP_VendorID, PNPVENDORID + JNE PnP_IsolateNextCard +; Cmp PnP_SerialID, PNPSERIALID +; JNE PnP_IsolateNextCard + + Mov AL, 3 + Call PnP_WriteData + + Mov AX, 07h ; Configuration device + Call PnP_WriteData + + Mov AL, 64h + Call PnP_ReadData + Mov AH, AL + Mov AL, 65h + Call PnP_ReadData ; AX = address. + + Test AX, AX + JZ PnP_IsolateNextCard + + Cmp BasePort, 0FFFFh + JE PnPBasePortOK + + Cmp BasePort, AX + JNE PnP_IsolateNextCard + +PnPBasePortOK: + Mov BasePort, AX + + Mov AL, 70h + Call PnP_ReadData ; AL[3:0] = IRQ + And AX, 15 + JZ PnP_IsolateNextCard + Mov IRQ, AX + + Mov AL, 75h + Call PnP_ReadData ; AL[2:0] = DMA + And AX, 7 + Cmp AL, 4 + JE PnP_IsolateNextCard + Mov DMA, AX + + Mov Pnp_CardFound, 1 + Jmp PnP_IsolateNextCard + +PnP_IsolateFinished: + Mov AL, PnP_CSN + ShL AL, 1 + Or AL, PnP_CardFound + + Ret + +EndP PnP_Isolate + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectMMX + + PushFD + Pop EAX + Mov EBX, EAX + Xor EAX, 00200000h + Push EAX + PopFD + PushFD + Pop EAX + Cmp EAX, EBX + JZ DetectMMXFail + + Mov EAX, 1 + DB 0Fh, 0A2h ; CPUID + Test EDX, 800000h + JZ DetectMMXFail + + ClC + Ret + +DetectMMXFail: + StC + Ret + +EndP DetectMMX + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far ; returns carry clear if succesful + + Push CS + Pop DS + + Call DetectMMX + JC DetectCard_MMXNotFound + + Xor AL, AL + Mov DX, 279h + Out DX, AL + Out DX, AL + + Mov AL, 6Ah ; Starting value + Mov CX, 32 + +PnP_InitiationKeyLoop: + Out DX, AL + + Mov AH, AL + ShR AH, 1 + Xor AH, AL + ShR AX, 1 + + Dec CX + JNZ PnP_InitiationKeyLoop + +; Try three ports before concluding no PnP cards: 20Fh, 27Bh, 213h + +PnP_DetectCardPort1: + Mov PnP_ReadPort, 20Fh + Call PnP_Isolate + JZ PnP_DetectCardPort2 + Test AL, 1 + JZ PnP_DetectCardNotFound + Jmp PnP_DetectCardFound + +PnP_DetectCardPort2: + Mov PnP_ReadPort, 27Bh + Call PnP_Isolate + JZ PnP_DetectCardPort3 + Test AL, 1 + JZ PnP_DetectCardNotFound + Jmp PnP_DetectCardFound + +PnP_DetectCardPort3: + Mov PnP_ReadPort, 213h + Call PnP_Isolate + Test AL, 1 + JNZ PnP_DetectCardFound + +PnP_DetectCardNotFound: + Mov AX, 202h + Call PnP_WriteData + +DetectCard_MMXNotFound: + StC + Ret + +PnP_DetectCardFound: + ClC + +PnP_DetectEnd: ; Return PnP to wait for key state + Mov AX, 202h + Call PnP_WriteData + + Mov EAX, 'Jeff' + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include mmxmsam.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WSSIRQHandler + + PushAD + Push DS + Push ES + + ClD + + Mov AX, CS + Mov DS, AX + Assume DS:Driver + + Mov DX, [BasePort] + Add DX, 2 + In AL, DX + Test AL, 1 + JZ WSSAckIRQ2 + + Xor AL, AL + Out DX, AL + +WSSAckIRQ2: + Mov AL, 20h + Cmp IRQ, 8 + JB WSSAckIRQ1 + + Out 0A0h, AL + +WSSAckIRQ1: + Out 20h, AL + + FNSave [FPSave] + + Mov AX, MixBufferPos + Mov BX, AX + Mul DMASize + Cmp AX, DMABUFFERLENGTH + JB WSSIRQHandler2 + + Xor AX, AX + Xor BX, BX + +WSSIRQHandler2: + Inc BX + Mov MixBufferPos, BX + + CLD + + ; OK... time to get next block + ; Check whether stereo thing is on.. + ; + LES DI, [ActualDMAPtr] + Mov BX, DMASize ; BX = bytes required + Add DI, AX + + ShR BX, 1 + ; BX = samples required + Call SaveEMSPageFrame + + Cmp MixTransferRemaining, 0 + JNE WSSIRQHandler4 + Assume DS:Nothing + +WSSIRQHandler3: + Push BX + Push CX + Push BP + Push ES + Push DI + + Call Update + Call MixSamples + + Pop DI + Pop ES + Pop BP + Pop CX + Pop BX + +WSSIRQHandler4: + Mov DS, MixSegment + Mov SI, MixTransferOffset + Mov DX, BX ; DX = samples to transfer + Cmp DX, MixTransferRemaining + JBE WSSIRQHandler5 + + Mov DX, MixTransferRemaining + +WSSIRQHandler5: + +include mmxtrans.inc + + Sub MixTransferRemaining, DX ; } Memory write + Sub BX, DX + JNZ WSSIRQHandler3 + + Mov MixTransferOffset, SI ; } Memory write + + Call RestoreEMSPageFrame + + FNRstor [CS:FPSave] + + Pop ES + Pop DS + PopAD + IRet + +EndP WSSIRQHandler + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Add DI, Offset IRQData + Mov BX, [CS:DI] + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset WSSIRQHandler + + XChg [ES:BX], EAX + Mov OldWSSIRQHandler, EAX + + Mov AX, IMR + And AX, [DI+2] + + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Pop ES + PopAD + + Ret + +EndP SetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Mov BX, [IRQData+DI] + + Mov EAX, OldWSSIRQHandler + Mov [ES:BX], EAX + + Pop ES + PopAD + + Ret + +EndP ResetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StopWSS + + Trace "GUSPnP MMX: StopSound" + + Mov DX, BasePort + + Mov AL, CODEC_INDEX_INTF + Out DX, AL + Inc DX + In AL, DX + And AL, Not INTF_PEN + Out DX, AL + + Inc DX + In AL, DX + Xor AL, AL + Out DX, AL + + Dec DX + Dec DX + + Mov AL, CODEC_INDEX_PIN + Out DX, AL + Inc DX + Xor AL, AL + Out DX, AL + + Ret + +EndP StopWSS + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StartWSS + + PushA + Push ES + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Trace "GUSPnP MMX: StartSound" + + ; Setup DMA + Mov BX, MixSegment + Mov AX, 80 + Mov DX, DMA + Mov DI, DMABUFFERLENGTH + Call SetDMA + + LES DI, ActualDMAPtr + Xor AX, AX + Mov CX, DMABUFFERLENGTH/2 + Rep StosW + + Mov MixBufferPos, 0 + Mov MixTransferRemaining, 0 + + Mov DX, BasePort + Call PingWSS + + Mov AL, CODEC_INDEX_PIN + Out DX, AL + Inc DX + Mov AL, PIN_IEN + Out DX, AL + Dec DX + + Mov AH, WSSMixConst ; Set format/frequency + Cmp Stereo, 0 + JE StartWSS1 + + Or AH, CDF_STEREO + +StartWSS1: + Mov AL, CODEC_MCE or CODEC_INDEX_CDF + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Call WaitCodec + + Mov AL, CODEC_INDEX_CDF + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Call WaitAutoCalibration + + ; Start playback + Mov AL, CODEC_INDEX_LWR_COUNT + Out DX, AL + Inc DX + + Mov AX, DMASize + ShR AX, 1 + + Cmp Stereo, 0 + JE StartWSS2 + + ShR AX, 1 + +StartWSS2: + Dec AX + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_UPR_COUNT + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_INTF + Out DX, AL + Inc DX + In AL, DX + Or AL, INTF_PEN + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_LDC + Out DX, AL + Inc DX + In AL, DX + And AL, Not LDC_LDM + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_RDC + Out DX, AL + Inc DX + In AL, DX + And AL, Not RDC_RDM + Out DX, AL + Dec DX + + Pop DS + Pop ES + PopA + + Ret + +EndP StartWSS + Assume DS:Nothing + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Trace "GUSPnP MMX: InitSound" + + Mov SI, Offset RelocationTable + +RelocationFix: + LodsW + Test AX, AX + JZ RelocationEnd + Mov BX, AX + Mov [BX], DS + Jmp RelocationFix + + +RelocationEnd: + Call GetEMSPageFrame + Mov EMSPageFrame, AX + + In AL, 0A1h + Mov AH, AL + In AL, 21h + Mov IMR, AX + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + Call GetWSSMixConst + + Mov AX, 2643 + Mul MixSpeed + Add AX, 0FFFFh + AdC DX, (DMABUFFERLENGTH*2)/16 + 5 + Mov BX, DX + + ; Allocate MixSegment first + Mov AH, 48h + + Int 21h + JNC InitSound1 + +InitSoundNoMemory: + Mov SI, Offset WSSNoMemoryMsg + Ret + +InitSound1: + Mov MixSegment, AX + + Call SetIRQ + Call GetTempo + Call SetTempo + + Call UpdateSoundcardVariables + + Mov SI, Offset WSSMsg + + Mov AX, BasePort + Mov BX, IRQ + Mov CX, DMA + + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Call ResetIRQ + Call SetIRQ + + Mov SI, Offset ReInitMsg + Mov BX, 40 + Call SetInfoLine + + Mov AL, Stereo + Call SetStereo + + Pop ES + Pop DS + PopA + + Ret + +EndP ReInitSound + Assume DS:Nothing + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, IMR + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Mov AX, MixSegment + Test AX, AX + JZ UnInitSound1 + + Mov ES, AX + Mov AH, 49h ; Release MixSegment + Int 21h + + Call StopWSS + Call ResetIRQ + +UnInitSound1: + Call GotoHomeDirectory + + ; Now to save config into driver file. + Mov AX, 3D02h ; Read write access + Mov DX, Offset DriverName + Int 21h + JC SetMixMode1 + + Mov BX, AX + + Mov AX, 4200h + Xor CX, CX + Mov DX, Offset CONFIGURATIONOFFSET + Int 21h + JC SetMixMode2 + + Mov AH, 40h + Mov CX, CONFIGSIZE + Mov DX, Offset MixMode + Int 21h + +SetMixMode2: + Mov AH, 3Eh + Int 21h + +SetMixMode1: + Ret + +EndP UnInitSound + Assume DS:Nothing + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + Ret + +EndP Poll + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Push AX + Push BX + Push DX + + Push BX + + Mov AX, MixSpeed + Mov BX, AX + Xor DX, DX + + ShL AX, 1 + RCL DX, 1 ; DX:AX = Mixspeed*2 + + ShR BX, 1 ; BX = Mixspeed/2 + + Add AX, BX + AdC DX, 0 ; DX:AX = Mixspeed*2.5 + + Pop BX ; BX = tempo + Div BX + + Mov BytesToMix, AX + + Pop DX + Pop BX + Pop AX + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + Mov CS:MixVolume, AX + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Jmp CS:RecalculateAllVolumes + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc RecalculateAllFrequencies + + Call GetChannelTables + +RecalculateAllFrequencies1: + Or Byte Ptr [SI], 32 + + Add SI, 128 + Dec CX + JNZ RecalculateAllFrequencies1 + + Ret + +EndP RecalculateAllFrequencies + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Trace "GUSPnP MMX: SetStereoCall" + + Mov CS:Stereo, AL + Cmp CS:MixSegment, 0 + JE SetStereo1 + + Call StopWSS + Call StartWSS + + Call RecalculateAllFrequencies + +SetStereo1: + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include loadsam.inc + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset WSS16ScreenList + + Trace "GUSPnP MMX: Driver Screen" + + ClC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far + + Xor AH, AH + Mov AL, [CS:VolumeTable+DI] + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UpdateSoundcardVariables + + Push AX DX + + Push CS + Pop DS + Assume DS:Driver + + Mov DX, BasePort + + Mov AL, CODEC_INDEX_LDC + Out DX, AL + Inc DX + Mov AX, 3F3Fh + Sub AX, [Word Ptr VolumeTable] + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_RDC + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Pop DX AX + Ret + +EndP UpdatesoundcardVariables + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far + + Push DS + Push DX + + Push CS + Pop DS + Assume DS:Driver + + Mov [VolumeTable+DI], AL + Call UpdateSoundcardVariables + + Pop DX + Pop DS + Ret + +EndP SetVariable + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +InterpretState DB 0 +InterpretType DB 0 + +Proc SendUARTOut Far ; Local interpreter activated with 0F0h 0F0h. + + Mov AH, CS:InterpretState + Cmp AH, 2 + JB SendUARTOut1 + +; In interpreter. + JE SendUARTOut3 + +; Have InterpretType, now get parameter, then return to normal. + + Cmp AL, 7Fh + JA SendUARTOut4 + + Push BX + + Mov BL, CS:InterpretType ; Want BX = InterpretType*64+Channel + ; + ShL BX, 6 + Add BL, [DI+20h] + And BX, 127 + Mov [CS:FilterParameters+BX], AL + + Pop BX + + Test SI, SI + JZ SendUARTOut4 + + Or Byte Ptr [SI], 64 + +SendUARTOut4: + Mov CS:InterpretState, 0 + Ret + +SendUARTOut3: + Cmp AL, 2 + JAE SendUARTOut4 + + Mov CS:InterpretType, AL + Jmp SendUARTOutStateInc + +SendUARTOut1: + Cmp AL, 0F0h + JNE SendUARTOut2 + +SendUARTOutStateInc: + Inc CS:InterpretState + Ret + +SendUARTOut2: + Test AH, AH + JZ SendUARTOutEnd + + Push AX + Mov AL, 0F0h +; Call UARTOut + Pop AX + Mov CS:InterpretState, 0 + +SendUARTOutEnd: + Cmp AL, 0FCh + JE ResetFilters + Cmp AL, 0FAh + JE ResetFilters + + Cmp AL, 0FFh + JNE SendUARTOutNoClear + +ResetFilters: + PushA + Push ES + + Push CS + Pop ES + + Mov DI, Offset FilterParameters + Mov CX, 64 + Mov AL, 7Fh + Rep StosB + Mov CX, 64 + Xor AX, AX + Rep StosB + + Pop ES + PopA + +SendUARTOutNoClear: +; Call UARTOut + Ret + +EndP SendUARTOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. + +StopAfterPlay DW 0 +DefaultChannels DW 128 + DW 3 + DW 4 Dup (0) + + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + DW Offset SendUARTOut + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/GUSRAMP.INC b/SoundDrivers/GUSRAMP.INC new file mode 100755 index 0000000..15c3271 --- /dev/null +++ b/SoundDrivers/GUSRAMP.INC @@ -0,0 +1,114 @@ + +Proc SetGUSVolume ; BX = new volume + + ; To do: + ; 1) Set ramp start + ; 2) Set ramp end + ; 3) Set current volume + ; 4) Start ramp + ; 5) Save new volume. + + Push BX + Push CX + + Mov AL, 0Dh + Out DX, AL + + Mov AL, 3 ; Stop Ramp! + Add DL, 2 + Out DX, AL + Call GUSDelay + Out DX, AL + Sub DL, 2 + + Add BX, BX + Mov CX, [CS:GUSVolumeTable+BX] ; CX = new volume + Mov BX, [SI+2] + Add BX, BX + Mov BX, [CS:GUSVolumeTable+BX] ; BX = old volume + + Cmp BX, CX + JNE SetGUSVolume2 + + Mov AL, 89h + Out DX, AL + Inc DX + In AX, DX + Dec DX + + Mov BX, AX ; BX = old volume + +SetGUSVolume2: + + Push BX ; Old volume on stack + + Xor AH, AH ; Ramp up + Cmp CX, BX + JAE SetGUSVolume1 + + XChg BX, CX + Mov AH, 40h ; Ramp down + +SetGUSVolume1: + Mov AL, 6 ; Ramp rate + Out DX, AL + + Mov AL, Byte Ptr CS:UsedChannels + ShR AL, 1 + Add AL, 16 + Add DL, 2 + Out DX, AL + Sub DL, 2 + + Mov AL, 7 ; Ramp start + Out DX, AL + + Mov AL, BH + Add DL, 2 + Out DX, AL + Call GUSDelay + Out DX, AL + Sub DL, 2 + + Mov AL, 8 ; Ramp end + Out DX, AL + + Mov AL, CH + Add DL, 2 + Out DX, AL + Call GUSDelay + Out DX, AL + Sub DL, 2 + + Mov AL, 9 + Out DX, AL + + Pop BX ; BX = old volume + XChg BX, AX + + Inc DX + Out DX, AX + Call GUSDelay + Out DX, AX + Dec DX + + Mov AL, 0Dh ; Ramp control + Out DX, AL + + Mov AL, BH + Add DL, 2 + Out DX, AL + Call GUSDelay + Out DX, AL + Sub DL, 2 + + Pop CX + Pop BX + + Mov [SI+2], BX + + Ret + +EndP SetGUSVolume + + diff --git a/SoundDrivers/GUSRIC.INC b/SoundDrivers/GUSRIC.INC new file mode 100755 index 0000000..cad6258 --- /dev/null +++ b/SoundDrivers/GUSRIC.INC @@ -0,0 +1,651 @@ + +Proc SetGUSRegisters ; Given DS:SI, CX + + Mov ES, CS:SongDataArea + + Push CX + Push SI + + Xor AX, AX + +GetOffsetLoop: + Push AX + Push CX + + Mov DX, GUSVoiceSelect + Out DX, AL ; OK.. now to play with this + ; voice. + Call GUSDelay + + Inc DL ; DX = select rego + + Mov BX, [SI] + Test BH, 2 + JZ GetOffsetLoop2 + + Mov BX, 200h + Mov [SI], BX + +GetOffsetLoop2: + Test BL, 1 ; Channel not on! + JZ GetOffsetLoop1 + + Test BH, 1 + JZ GetOffsetLoop3 ; Prev 1. + + Xor BX, BX + Call SetGUSVolume + + Mov AL, 80h + Out DX, AL + Add DL, 2 + In AL, DX + Sub DL, 2 + Mov AH, AL + + And AX, 400h + Out DX, AL ; AL = 0 (Mode control) + Mov AL, 3 + Or AL, AH + Add DL, 2 + Out DX, AL + Call GUSDelay + Out DX, AL + Sub DL, 2 + + Jmp GetOffsetLoop1 + +GetOffsetLoop3: + Mov EAX, [SI+4Ch] + Mov [SI+2Ch], EAX + + Mov AL, 8Ah + Out DX, AL + + Inc DX + In AX, DX + Dec DX + + And AH, 31 + ShL EAX, 16 ; Load high part of EAX + + Mov AL, 8Bh + Out DX, AL + Inc DX + In AX, DX + ; EAX = 000OOOOO OOOOOOOO OOOOOOOF FFFFFFFF + ; Need: 00000000 0000OOOO OOOOOOOO OOOOOOOO + + ShR EAX, 9 + ; EAX contains current loc. + ; Convert to Offset (in sample) + MovZX EBX, Byte Ptr [SI+36h] + Sub EAX, [CS:GUSDataTable+EBX*4] + Push CX + + Mov CL, CS:Compress + ShL EAX, CL + + Pop CX + Mov [SI+4Ch], EAX + Cmp EAX, [SI+44h] + JBE GetOffsetLoop1 + + Cmp Byte Ptr [SI+0Ah], 0 + JNE GetOffsetLoop1 + + Or Word Ptr [SI], 200h + +GetOffsetLoop1: + Add SI, SLAVECHANNELSIZE + + Pop CX + Pop AX + + Inc AX + Dec CX + JNZ GetOffsetLoop + + Pop SI + Pop CX + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + + Push CX + Push SI + + Push SI + + Mov BX, 1 + Mov DX, 1 + +ReinitChannels1: + Test Byte Ptr [SI], 1 + JZ ReinitChannels2 + + Mov BX, DX + +ReinitChannels2: + Inc DX + Add SI, 128 + Loop ReinitChannels1 + + Pop SI + + Mov CX, BX + + Cmp BX, 14 + JAE RIC3 + + Mov BX, 14 + +RIC3: + Cmp BX, 32 + JB RIC4 + + Mov BX, 32 + +RIC4: + Cmp BX, CS:UsedChannels + JE EndOfFreqChange + + JA RIC5 + Mov BX, CS:UsedChannels + Dec BX + +RIC5: + ; Now.. get new mixspeed. + ; Prepare all new frequencies + ; then write all active voices + ; + all new frequencies. + ; BX = num channels... + Push BX + Push BX + Push BX + + Add BX, BX ; BX = pointer into mixtable. + MovZX EBX, [CS:GUSMixTable+BX-28] + Mov CS:MixSpeed, BX + + Push CX + Push SI + +PrepareNewFreq2: + Test Byte Ptr [SI], 1 + JZ PrepareNewFreq3 + + Test Word Ptr [SI], 100h + JNZ PrepareNewFreq3 + + Mov EAX, [SI+10h] ; EAX = freq. + Push CX + Mov CL, CS:Compress + ShR EAX, CL + Pop CX + Xor EDX, EDX + + Div EBX ; EAX = I portion. + + Push EAX + Xor EAX, EAX + Div EBX + + Pop EDX ; EDX:EAX = IIII FFFF etc. + + SHRD EAX, EDX, 22 + Add AX, 1 + SBB AX, 0 ; Just in case! + And AX, Not 1 + Mov [SI+4], AX + +PrepareNewFreq3: + Add SI, 128 + Loop PrepareNewFreq2 + + Pop SI + Pop CX + + Pop BX + + Mov DI, CS:UsedChannels + Cmp DI, BX + JB KillExtraChannels1 + + Mov DI, BX + Mov BX, 32 +; XChg DI, BX + +KillExtraChannels1: + Cmp DI, BX + JAE KillExtraChannels2 + + Mov DX, GUSVoiceSelect + Mov AX, DI + Out DX, AL + + Inc DX ; Select rego + + Mov AL, 0Dh ; Volume Ramp. + Out DX, AL + + Mov AL, 3 + Add DL, 2 + Out DX, AL + Sub DL, 2 + + Xor AL, AL + Out DX, AL ; AL = 0 (Mode control) + Mov AL, 3 + Add DL, 2 + Out DX, AL + Sub DL, 2 + + Mov AL, 9 + Out DX, AL + Xor AX, AX + Inc DX + Out DX, AX + Dec DX + + Mov AL, 0Ch ; Set panning. + Out DX, AL + Mov AL, 8 + Add DL, 2 + Out DX, AL + Sub DL, 2 + + Comment ~ + + Call GUSDelay + + Mov AL, 0Dh ; Volume Ramp. + Out DX, AL + + Mov AL, 3 + Add DL, 2 + Out DX, AL + Sub DL, 2 + + Xor AL, AL + Out DX, AL ; AL = 0 (Mode control) + Mov AL, 3 + Add DL, 2 + Out DX, AL + Sub DL, 2 + + Mov AL, 9 + Out DX, AL + Xor AX, AX + Inc DX + Out DX, AX + Dec DX + + Mov AL, 0Ch ; Set panning. + Out DX, AL + Mov AL, 8 + Add DL, 2 + Out DX, AL + Sub DL, 2 + + ~ + + Inc DI + Jmp KillExtraChannels1 + +KillExtraChannels2: + Xor BX, BX ; BX = channel number + +PrepareNewFreq4: + Mov DX, GUSVoiceSelect + Mov AL, BL + Out DX, AL + Inc DX ; Select rego + + Test Byte Ptr [SI], 1 + JZ PrepareNewFreq5 + + Test Word Ptr [SI], 120h ; New note or new freq? + JNZ PrepareNewFreq5 + + Or Byte Ptr [SI], 2h + + Mov AL, 1 + Out DX, AL + Inc DX + Mov AX, [SI+4] + Out DX, AX + +PrepareNewFreq5: + Inc BX + Add SI, 128 + Loop PrepareNewFreq4 + + Mov DX, GUSRegisterSelect + Mov AL, 0Eh + Out DX, AL + Add DL, 2 + Pop AX + Dec AL + Or AL, 0C0h + Out DX, AL + + Pop CS:UsedChannels + +EndOfFreqChange: + + Pop SI + Pop CX + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + Xor AX, AX + +SetGUSRegisters1: + Push AX + Push CX + + Mov DX, GUSVoiceSelect + Out DX, AL ; OK.. now to play with this + ; voice. + Call GUSDelay + + Mov CX, [SI] ; CX = flags. + Inc DL ; DX = select rego + +SetGUSRegisters21: + Test CL, 32 ; Frequency change + JZ SetGUSRegisters7 + + Push DX + + Mov EAX, [SI+10h] ; EAX = freq. + + Push CX + Mov CL, CS:Compress + ShR EAX, CL + Pop CX + + Xor EDX, EDX + MovZX EBX, MixSpeed + + Div EBX ; EAX = I portion. + + Test EAX, Not 63 + JNZ SetGUSRegisters6 + + Push EAX + + Xor EAX, EAX + Div EBX + + Pop EBX ; EBX:EAX = IIII FFFF etc. + + SHRD EAX, EBX, 6 + + ; Have: IIIIIIII IIIIIIII FFFFFFFF FFFFFFFF + ; Req: IIIIIIFF FFFFFFF0 + + Pop DX + Mov AL, 1 + Out DX, AL + + ShR EAX, 16 + Add AX, 1 + SBB AX, 0 ; Just in case! + And AX, Not 1 + + Inc DX + Out DX, AX + Dec DX + + Jmp SetGUSRegisters7 + +SetGUSRegisters6: + Mov CH, 2 ; Signify to turn off channel + Pop DX + +SetGUSRegisters7: + MovZX BX, Byte Ptr [SI+36h] ; BX = sample number. + Cmp BL, 99 + JA SetGUSRegisters20 + + ShL BX, 2 ; GUSDataTable+BX = position + + Cmp DWord Ptr [CS:GUSDataTable+BX], 0FFFFFFFFh + JNE SetGUSRegisters10 + +SetGUSRegisters20: + Mov CH, 2 + Jmp SetGUSRegisters9 + +SetGUSRegisters10: + Test CX, 502h ; Loop changed?!??!? + JZ SetGUSRegisters8 + + Mov AL, 3 ; Starting location low. + Out DX, AL + + Mov EAX, [SI+40h] + Call GUSGetAddress + + ; Reqd: ...OOOOO OOOOOOOO OOOOOOOI III..... + + Inc DX + Out DX, AX + Dec DX + + Mov AL, 2 ; Starting location high + Out DX, AL + + ShR EAX, 16 + Inc DX + Out DX, AX + Dec DX + + ; Ending location... + Mov AL, 5 ; Ending location low + Out DX, AL + + Mov EAX, [SI+44h] + Call GUSGetAddress + + Inc DX + Out DX, AX + Dec DX + + Mov AL, 4 ; Ending location high + Out DX, AL + + SHR EAX, 16 + Inc DX + Out DX, AX + Dec DX + +SetGUSRegisters8: + Test CH, 1 ; Do Current position? + JZ SetGUSRegisters9 + + Mov AL, 0Bh ; Current location LOW + Out DX, AL + + Mov EAX, [SI+4Ch] + Mov [SI+2Ch], EAX + + ; EAX = OOOOOOOO OOOOOOOO OOOOOOOO OOOOOOOO + ; Req: xxxOOOOO OOOOOOOO OOOOOOOF FFFFFFFF + Call GUSGetAddress + + Mov DI, AX + + Inc DX + Out DX, AX + Dec DX + + Mov AL, 0Ah ; Current location HIGH + Out DX, AL + + SHR EAX, 16 + Inc DX + Out DX, AX + Call GUSDelay + Out DX, AX + Dec DX + + Mov AL, 0Bh + Out DX, AL + + Mov AX, DI + Inc DX + Out DX, AX + Dec DX + +SetGUSRegisters9: + Test CL, 64 ; New volume?? + JZ SetGUSPanning + +SetGUSRegisters23: + Xor BX, BX + Test CH, 8 + JNZ SetGUSRegistersMuted + + Mov BL, Byte Ptr [SI+20h] ; BL = volume, 0->128 + +SetGUSRegistersMuted: + Call SetGUSVolume + + +SetGUSPanning: + Test CH, 128 ; New panning? + JZ SetGUSRegisters5 + + Mov AL, 0Ch ; Set panning. + Out DX, AL + + Test CS:Stereo, 1 + JZ SetGUSRegisters3 + + Mov AL, [SI+37h] + Cmp AL, 100 + JNE SetGUSRegisters4 + +SetGUSRegisters3: + Mov AL, 32 ; Surround goes to mono :( + +SetGUSRegisters4: ; AL = 0->64 + ShR AL, 1 ; AL = 0->32 + Sub AL, 1 + AdC AL, 0 ; AL = 0->31 + ShR AL, 1 + + Add DL, 2 + Out DX, AL + Sub DL, 2 + +SetGUSRegisters5: + ; Now for control register. + ; If CH | 2, then turn rego OFF + ; If CH | 5, then turn rego ON + ; If CL | 1, then check channel + Test CH, 2 + JNZ SetGUSRegisters11 + + Test CH, 5 + JNZ SetGUSRegisters12 + + Test CL, 1 + JZ SetGUSRegisters13 + + Mov AL, 80h ; Read voice control + Out DX, AL + + Add DL, 2 + In AL, DX + Sub DL, 2 + + Test AL, 1 + JZ SetGUSRegisters13 + + Xor BX, BX + Call SetGUSVolume + + Jmp SetGUSRegisters14 + +SetGUSRegisters11: + ; Turn off. + Xor AL, AL + Out DX, AL ; AL = 0 (Mode control) + Mov AL, 2 + Add DL, 2 + + Mov AH, [SI+18h] ; 16 bit? + Add AH, AH + Or AL, AH + + Out DX, AL + Call GUSDelay + Out DX, AL + Sub DL, 2 + + Xor BX, BX + Call SetGUSVolume + +SetGUSRegisters14: + Test CL, 1 + JZ SetGUSRegisters13 + + Xor CX, CX ; Turn off channel + Test Byte Ptr [SI+3Ah], 80h + JNZ SetGUSRegisters13 + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Signify channel off + + Jmp SetGUSRegisters13 + +SetGUSRegisters12: ; Turn on + Xor AL, AL + Out DX, AL + + Mov AL, [SI+0Ah] + + Cmp CS:Convert16To8Bit, 0 + JNZ SetGUSRegistersNo16Bit + + Mov AH, [SI+18h] ; 16 bit? + Add AH, AH + Or AL, AH + +SetGUSRegistersNo16Bit: + Test CL, 1 + JNZ SetGUSRegisters15 + + Mov AL, 2 + Xor CX, CX + +SetGUSRegisters15: + Add DL, 2 + Out DX, AL + Call GUSDelay + Out DX, AL + +SetGUSRegisters13: + And CX, 0111100010011111b ; Turns off: + ; 1) Freq, pan & vol recalc + ; 2) New note/note stop/loop cha + + Mov [SI], CX + + Add SI, SLAVECHANNELSIZE + + Pop CX + Pop AX + + Inc AX + Dec CX + JNZ SetGUSRegisters1 + + Ret + + +EndP SetGUSRegisters + + diff --git a/SoundDrivers/IRQ.INC b/SoundDrivers/IRQ.INC new file mode 100755 index 0000000..464402b --- /dev/null +++ b/SoundDrivers/IRQ.INC @@ -0,0 +1,20 @@ + +IRQData Label Word + DW 20h, 1111111111111110b ; IRQ 0 + DW 24h, 1111111111111101b ; IRQ 1 + DW 28h, 1111110111111011b ; IRQ 2 + DW 2Ch, 1111111111110111b ; IRQ 3 + DW 30h, 1111111111101111b ; IRQ 4 + DW 34h, 1111111111011111b ; IRQ 5 + DW 38h, 1111111110111111b ; IRQ 6 + DW 3Ch, 1111111101111111b ; IRQ 7 + DW 1C0h, 1111111011111011b ; IRQ 8 + DW 1C4h, 1111110111111011b ; IRQ 9 + DW 1C8h, 1111101111111011b ; IRQ 10 + DW 1CCh, 1111011111111011b ; IRQ 11 + DW 1D0h, 1110111111111011b ; IRQ 12 + DW 1D4h, 1101111111111011b ; IRQ 13 + DW 1D8h, 1011111111111011b ; IRQ 14 + DW 1DCh, 0111111111111011b ; IRQ 15 + + diff --git a/SoundDrivers/IWCODEC.ASM b/SoundDrivers/IWCODEC.ASM new file mode 100755 index 0000000..7598505 --- /dev/null +++ b/SoundDrivers/IWCODEC.ASM @@ -0,0 +1,2302 @@ +; +; Windows Sound System Driver, for GUS PnP +; + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;********************************** + +STEREOENABLED EQU 1 +DMABUFFERLENGTH EQU 8192 +MIXRESOLUTION EQU 32 ; 32 bit mixing for +MIXTABLESIZE EQU 2*256*65 + +DMASize DW 2048 + +WSSMsg DB "Using GUS CS4231 Codec", 13 + DB "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, DMA ", 0FDh, "D", 0 + +WSSNoMemoryMsg DB "Using GUS CS4231 Codec", 13 + DB "Error: Insufficient memory", 0 + +ReinitMsg DB "GUS Codec reinitialised", 0 + +ConfigErrorMsg DB "Error saving configuration to ITGUSMAX.DRV", 0 +ConfigOKMsg DB "Configuration saved to ITGUSMAX.DRV", 0 + +DriverName DB "ITGUSMAX.DRV", 0 + +Forced DB 0 +Stereo DB 0 +MixVolume DW 0 + +BytesToMix DW 1000 +WSSMixConst DB 0 + +MixSegment DW 0 +DMASegment DW 0 + +MixTransferOffset DW 0 +MixTransferRemaining DW 0 + +CONFIGURATIONOFFSET EQU $+128 +CONFIGSIZE EQU 6 +MixMode DW 0 +MixModeOffset DW 0 +Filter DW 0 + +IMR DW 0 +OldWSSIRQHandler DD 0 + +FilterValue DD 0 +FilterValue2 DD 0 + +MixSpeedTable DW 5513, 41h + DW 6615, 4Fh + DW 8000, 40h + DW 9600, 4Eh + DW 11025, 43h + DW 16000, 42h + DW 18900, 45h + DW 22050, 47h + DW 27429, 44h + DW 32000, 46h + DW 33075, 4Dh + DW 37800, 49h + DW 44100, 4Bh + DW 48000, 4Ch + DW 54860, 48h + DW 64000, 4Ah + +IRQData Label Word + DW 20h, 1111111111111110b ; IRQ 0 + DW 24h, 1111111111111101b ; IRQ 1 + DW 28h, 1111110111111011b ; IRQ 2 + DW 2Ch, 1111111111110111b ; IRQ 3 + DW 30h, 1111111111101111b ; IRQ 4 + DW 34h, 1111111111011111b ; IRQ 5 + DW 38h, 1111111110111111b ; IRQ 6 + DW 3Ch, 1111111101111111b ; IRQ 7 + DW 1C0h, 1111111011111011b ; IRQ 8 + DW 1C4h, 1111110111111011b ; IRQ 9 + DW 1C8h, 1111101111111011b ; IRQ 10 + DW 1CCh, 1111011111111011b ; IRQ 11 + DW 1D0h, 1110111111111011b ; IRQ 12 + DW 1D4h, 1101111111111011b ; IRQ 13 + DW 1D8h, 1011111111111011b ; IRQ 14 + DW 1DCh, 0111111111111011b ; IRQ 15 + +;********************************** +; WSS Registers +;********************************** + +CODEC_INDEX_LIC = 00 +CODEC_INDEX_RIC = 01h +CODEC_INDEX_LX1C = 02h +CODEC_INDEX_RX1C = 03h +CODEC_INDEX_LX2C = 04h +CODEC_INDEX_RX2C = 05h +CODEC_INDEX_LDC = 06h +CODEC_INDEX_RDC = 07h +CODEC_INDEX_CDF = 08h +CODEC_INDEX_INTF = 09h +CODEC_INDEX_PIN = 0Ah +CODEC_INDEX_TEST = 0Bh +CODEC_INDEX_MISC = 0Ch +CODEC_INDEX_DIGMIX = 0Dh +CODEC_INDEX_UPR_COUNT = 0Eh +CODEC_INDEX_LWR_COUNT = 0Fh + +CODEC_MCE = 40h + +LDC_LDM = 80h +LDC_LDA = 3Fh + +RDC_RDM = 80h +RDC_RDA = 3Fh + +CDF_STEREO = 10h + +INTF_PEN = 01h +INTF_CEN = 02h +INTF_SDC = 04h +INTF_ACAL = 08h +INTF_PPIO = 40h +INTF_CPIO = 80h + +PIN_IEN = 2 + +TEST_ORL = 03h +TEST_ORR = 0Ch +TEST_DRS = 10h +TEST_ACI = 20h +TEST_PUR = 40h +TEST_COR = 80h + +;********************************** + +WSS16ScreenList Label + DW 16 + DW Near Ptr IdleFunctionList + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr WSSHeaderLine + + DW Near Ptr DriverText + + DW Near Ptr MixModeText + DW Near Ptr MixModeButton1 ; 6 + DW Near Ptr MixModeButton2 ; + DW Near Ptr MixModeButton3 ; 8 + DW Near Ptr MixModeButton4 ; 9 + + DW Near Ptr FilterText + DW Near Ptr FilterButton1 ; 11 + DW Near Ptr FilterButton2 + DW Near Ptr FilterButton3 + + DW Near Ptr VolumeText + DW Near Ptr VolumeBox1 + + DW Near Ptr MasterVolumeLeft ; 16 + DW Near Ptr MasterVolumeRight ; 17 + + DW 0 + +WSSHeaderLine DW 10 + DB "GUS CS4231 Codec Driver", 0 + +EmptyObject DW 1 + DB 0, 0 + DB 0 + DB 0 + +DriverText DW 1 + DB 31, 48 + DB 21h + DB "GUS CS4231 Codec Driver 1.0 for Impulse Tracker", 0 + +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +IdleFunctionList DD 0 + DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +VolumeText DW 1 + DB 2, 14 + DB 20h + DB "Master Volume Left", 13 + DB "Master Volume Right" + DB 0 + +VolumeBox1 DW 0 + DB 21, 13, 31, 16 + DB 25 + +MasterVolumeLeft DW 9 + DB 22, 14 + DW 0, 63 + DW 9, 0 + DW 0FFFFh, 17, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +MasterVolumeRight DW 9 + DB 22, 15 + DW 0, 63 + DW 9, 1 + DW 16, 6, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +MixModeText DW 1 + DB 2, 18 + DB 20h + DB "Mixing Mode, Playback Frequency: ", 0FDh, "DHz", 0 +MixSpeed DW 48000 + +MixModeButton1 DW 2 + DW 17, 7, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment1 DW 0 + DW 0 + DW Offset SetMixMode +DriverSegment2 DW 0 + DB 3, 20, 32, 22, 8 + DB 0 + DB " 16 Bit, Non-Interpolated", 0 + +MixModeButton2 DW 2 + DW 6, 8, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment3 DW 0 + DW 2 + DW Offset SetMixMode +DriverSegment4 DW 0 + DB 3, 23, 32, 25, 8 + DB 0 + DB " 16 Bit, Interpolated", 0 + +MixModeButton3 DW 2 + DW 7, 9, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment5 DW 0 + DW 4 + DW Offset SetMixMode +DriverSegment6 DW 0 + DB 3, 26, 32, 28, 8 + DB 0 + DB " 32 Bit, Non-Interpolated", 0 + +MixModeButton4 DW 2 + DW 8, 11, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment7 DW 0 + DW 6 + DW Offset SetMixMode +DriverSegment8 DW 0 + DB 3, 29, 32, 31, 8 + DB 0 + DB " 32 Bit, Interpolated", 0 + +FilterText DW 1 + DB 2, 33 + DB 20h + DB "Filter mode", 0 + +FilterButton1 DW 2 + DW 9, 12, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment9 DW 0 + DW 0 + DW Offset SetFilter +DriverSegment10 DW 0 + DB 3, 35, 29, 37, 8 + DB 0 + DB " No Filter", 0 + +FilterButton2 DW 2 + DW 11, 13, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment11 DW 0 + DW 1 + DW Offset SetFilter +DriverSegment12 DW 0 + DB 3, 38, 29, 40, 8 + DB 0 + DB " 50% Filter", 0 + +FilterButton3 DW 2 + DW 12, 0FFFFh, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment13 DW 0 + DW 2 + DW Offset SetFilter +DriverSegment14 DW 0 + DB 3, 41, 29, 43, 8 + DB 0 + DB " 75% Filter", 0 + +VolumeTable DB 2 Dup (0) + +; ÄÄ MixingRoutines ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixBufferPos DW 0 + +include dma.inc +include mix.inc +include m12bit.mix +include m12biti.mix +include m32bit.mix +include m32biti.mix + +MixFunctionTables Label + +include m12bit.inc ; contains the tables +include m12biti.inc +include m32bit.inc +include m32biti.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +RelocationTable Label Word + DW Offset DriverSegment1, Offset DriverSegment2 + DW Offset DriverSegment3, Offset DriverSegment4 + DW Offset DriverSegment5, Offset DriverSegment6 + DW Offset DriverSegment7, Offset DriverSegment8 + DW Offset DriverSegment9, Offset DriverSegment10 + DW Offset DriverSegment11, Offset DriverSegment12 + DW Offset DriverSegment13, Offset DriverSegment14 + DW 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixMode Far + + Push CS + Pop ES + Mov DI, Offset MixMode + + Ret + +EndP GetMixMode + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetFilter Far + + Push CS + Pop ES + Mov DI, Offset Filter + + Ret + +EndP GetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetFilter Far + + Mov AX, [SI+22] + Mov CS:FilterValue, 0 + Mov CS:Filter, AX + ClI + Jmp SetMixModeChain + +EndP SetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WaitCoDec + + Push CX + + Mov CX, 0F000h + +WaitCoDec1: + In AL, DX + Test AL, AL + JNS WaitCoDec2 + Loop WaitCoDec1 + + StC + +WaitCoDec2: + Pop CX + Ret + +EndP WaitCoDec + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WaitAutoCalibration + + Push CX + Mov CX, 0F000h + +WaitAutoCalibration1: + Mov AL, CODEC_INDEX_TEST + Out DX, AL + Inc DX + In AL, DX + Dec DX + Test AL, TEST_ACI + JNZ WaitAutoCalibration2 + Loop WaitAutoCalibration1 + + StC + +WaitAutoCalibration2: + Pop CX + Ret + +EndP WaitAutoCalibration + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixMode Far + + Mov AX, [SI+22] + + ClI + + Mov CS:MixMode, AX + + Mov BX, 180 + Mul BX + Mov CS:MixModeOffset, AX + + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS:RecalculateAllVolumes + + StI + +SetMixModeChain: + Call GotoHomeDirectory + + ; Now to save config into driver file. + Push CS + Pop DS + Assume DS:Driver + + Mov AX, 3D02h ; Read write access + Mov DX, Offset DriverName + Mov SI, Offset ConfigErrorMsg + Int 21h + JC SetMixMode1 + + Mov BX, AX + + Mov AX, 4200h + Xor CX, CX + Mov DX, Offset CONFIGURATIONOFFSET + Int 21h + JC SetMixMode2 + + Mov AH, 40h + Mov CX, CONFIGSIZE + Mov DX, Offset MixMode + Int 21h + +SetMixMode2: + PushF + Mov AH, 3Eh + Int 21h + PopF + + JC SetMixMode1 + + Mov SI, Offset ConfigOKMsg + +SetMixMode1: + Mov BX, 40 + Call SetInfoLine + + Mov AX, 1 + Ret + +EndP SetMixMode + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetWSSMixConst ; Work out value.. and nearest + ; mixspeed value. + + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, CmdLineMixSpeed + Mov CX, MixSpeed + Test AX, AX + JZ GetWSSMixConst1 + + Mov CX, 64000 + Cmp AX, CX + JA GetWSSMixConst1 + + Mov CX, 8000 + Cmp AX, CX + JB GetWSSMixConst1 + + Mov CX, AX + +GetWSSMixConst1: ; CX = desired mixspeed + Mov SI, Offset MixSpeedTable + Mov DX, 16 ; 16 different available speeds + + Xor BX, BX + +GetWSSMixConst2: + LodsW + Cmp AX, BX + JB GetWSSMixConst3 + Cmp AX, CX + JA GetWSSMixConst3 + + Mov BX, AX + Mov DH, [SI] + +GetWSSMixConst3: + LodsW ; Add SI, 2 + Dec DL + JNZ GetWSSMixConst2 + + Mov MixSpeed, BX + Mov WSSMixConst, DH + + Pop DS + PopA + Ret + +EndP GetWSSMixConst + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PingWSS ; Check BasePort, DX = BasePort + ; Preserves DX, destroys AX + + Push DX + + Inc DX + Inc DX + + In AL, DX + Xor AL, AL + Out DX, AL + + Dec DX + Dec DX + Call WaitCodec + JC PingWSSFailure + + In AL, DX + Test AL, AL + JS PingWSSFailure + + Mov AL, CODEC_INDEX_MISC + Out DX, AL + Inc DX ; DX = Data port + In AL, DX + Mov AH, AL ; AH = Revision + + Xor AL, AL ; Write 0 revision + Out DX, AL + In AL, DX + And AX, 8F8Fh + Cmp AL, AH + JNE PingWSSFailure + Dec DX ; DX = AD1848 baseport + + Mov AL, CODEC_MCE or CODEC_INDEX_INTF + Out DX, AL + Inc DX + Mov AL, INTF_ACAL or INTF_SDC + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_INTF + Out DX, AL + Inc DX + Mov AL, INTF_ACAL or INTF_SDC + Out DX, AL + Dec DX + + Call WaitAutoCalibration ; Returns carry if error + ; Carry clear if none. + +; JC PingWSSFailure + + Pop DX + Ret + +PingWSSFailure: + Pop DX + + StC + Ret + + +EndP PingWSS + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +PnP_SerialID DD 0 +PnP_VendorID DD 0 +PnP_ReadPort DW 0 +PnP_CSN DB 0 +PnP_CardFound DB 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_Delay + Assume DS:Driver + + Push AX CX + + Mov CX, 180h +PnP_Delay1: + In AL, 21h + Loop PnP_Delay1 + + Pop CX AX + Ret + +EndP PnP_Delay + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_WriteData + + Mov DX, 279h + Out DX, AL + + Mov AL, AH + Mov DH, 0Ah + Out DX, AL + Ret + +EndP PnP_WriteData + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_ReadData + + Mov DX, 279h + Out DX, AL + + Mov DX, PnP_ReadPort + In AL, DX + + Ret + +EndP PnP_ReadData + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_Isolate + + Mov AX, 402h + Call Pnp_WriteData ; Reset CSNs + +PnP_IsolateNextCard: + Mov AX, 0003h + Call PnP_WriteData ; Wake[0] + + Mov AX, PnP_ReadPort + ShL AX, 6 + Xor AL, AL + Call PnP_WriteData ; Set Read Data port. + + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + + Mov AL, 1 ; Serial Isolation + Mov DX, 279h + Out DX, AL + + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + + Mov BL, 6Ah + Mov CX, 64 + Mov DX, PnP_ReadPort + + ClI + +PnP_Isolate1: + ShR PnP_SerialID, 1 + RCR PnP_VendorID, 1 + + Mov BH, BL + ShR BH, 1 + Xor BH, BL + ShR BX, 1 + + In AL, DX + Mov AH, AL + Call PnP_Delay + In AL, DX + Call PnP_Delay + + Cmp AX, 55AAh + JNE PnP_Isolate2 + + Xor BL, 80h + Or PnP_SerialID, 80000000h + +PnP_Isolate2: + Dec CX + JNZ PnP_Isolate1 + + Mov CX, 8 + Xor BH, BH + +PnP_Isolate3: + ShR BH, 1 + + In AL, DX + Mov AH, AL + Call PnP_Delay + In AL, DX + Call PnP_Delay + Cmp AX, 55AAh + JNE PnP_Isolate4 + + Or BH, 80h + +PnP_Isolate4: + Dec CX + JNZ PnP_Isolate3 + + StI + + Cmp BL, BH ; Matching Checksum? + JNE PnP_IsolateFinished + + ; assign CSN + Inc PnP_CSN + + Mov AL, 6 + MOv AH, PnP_CSN + Call PnP_WriteData + + Cmp PnP_VendorID, PNPVENDORID + JNE PnP_IsolateNextCard +; Cmp PnP_SerialID, PNPSERIALID +; JNE PnP_IsolateNextCard + + Mov AL, 3 + Call PnP_WriteData + + Mov AX, 07h ; Configuration device + Call PnP_WriteData + + Mov AL, 60h + Call PnP_ReadData + Mov AH, AL + Mov AL, 61h + Call PnP_ReadData ; AX = address. + + Test AX, AX + JZ PnP_IsolateNextCard + + Cmp BasePort, 0FFFFh + JE PnPBasePortOK + + Cmp BasePort, AX + JNE PnP_IsolateNextCard + +PnPBasePortOK: + Mov BasePort, AX + + Mov AL, 70h + Call PnP_ReadData ; AL[3:0] = IRQ + And AX, 15 + JZ PnP_IsolateNextCard + Mov IRQ, AX + + Mov AL, 74h + Call PnP_ReadData ; AL[2:0] = DMA + And AX, 7 + Cmp AL, 4 + JE PnP_IsolateNextCard + Mov DMA, AX + + Mov AX, 407h ; Configuration device + Call PnP_WriteData + + Mov AL, 60h + Call PnP_ReadData + Mov AH, AL + Mov AL, 61h + Call PnP_ReadData ; AX = address. + Test AX, AX + JZ PnP_IsolateNextCard + + Mov SAM9407Port, AX + + Mov Pnp_CardFound, 1 + Jmp PnP_IsolateNextCard + +PnP_IsolateFinished: + Mov AL, PnP_CSN + ShL AL, 1 + Or AL, PnP_CardFound + + Ret + +EndP PnP_Isolate + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far ; returns carry clear if succesful + + Push CS + Pop DS + + Xor AL, AL + Mov DX, 279h + Out DX, AL + Out DX, AL + + Mov AL, 6Ah ; Starting value + Mov CX, 32 + +PnP_InitiationKeyLoop: + Out DX, AL + + Mov AH, AL + ShR AH, 1 + Xor AH, AL + ShR AX, 1 + + Dec CX + JNZ PnP_InitiationKeyLoop + +; Try three ports before concluding no PnP cards: 20Fh, 27Bh, 213h + +PnP_DetectCardPort1: + Mov PnP_ReadPort, 20Fh + Call PnP_Isolate + JZ PnP_DetectCardPort2 + Test AL, 1 + JZ PnP_DetectCardNotFound + Jmp PnP_DetectCardFound + +PnP_DetectCardPort2: + Mov PnP_ReadPort, 27Bh + Call PnP_Isolate + JZ PnP_DetectCardPort3 + Test AL, 1 + JZ PnP_DetectCardNotFound + Jmp PnP_DetectCardFound + +PnP_DetectCardPort3: + Mov PnP_ReadPort, 213h + Call PnP_Isolate + Test AL, 1 + JNZ PnP_DetectCardFound + +PnP_DetectCardNotFound: + StC + Jmp PnP_DetectEnd + +PnP_DetectCardFound: + Mov DX, + ClC + +PnP_DetectEnd: ; Return PnP to wait for key state + Mov AX, 202h + Call PnP_WriteData + Mov EAX, 'Jeff' + + Ret + + Mov AL, CODEC_INDEX_RDC + Out DX, AL + Inc DX + In AL, DX + Mov AH, AL + Dec DX + + Mov AL, CODEC_INDEX_LDC + Out DX, AL + Inc DX + In AL, DX + And AX, 3F3Fh + Neg AL + Neg AH + Add AL, 3Fh + Add AH, 3Fh + Mov [Word Ptr VolumeTable], AX + + Mov EAX, 'Jeff' + ClC + +DetectCardEnd: + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixModeTable Label Word + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + +Proc MixSamples ; Given DS:SI = info tables, CX = numchannels + + ; 1. Clean buffer + ; + update variables + ; 2. Update parameters + ; 3. Mix func + ; 4. Return + + Push CX + + Mov CX, BytesToMix + Mov ES, MixSegment + Mov DI, MIXTABLESIZE + Xor EAX, EAX + Mov DX, CX + Add CX, CX + + Mov MixTransferOffset, DI ; } Memory write + + Cmp Stereo, 0 + JE MixSamples1 + + Mov DX, CX + +MixSamples1: + Rep StosD ; } Memory write + Mov MixTransferRemaining, DX ; } + + Pop CX + +MixSamples2: + Test Byte Ptr [SI], 1 + JZ MixSamplesEnd2 + Cmp Byte Ptr [SI+36h], 100 + JE MixSamplesEnd2 + + Push CX + Mov CX, [SI] + + Test CH, 2 + JZ MixSamples3 + And Byte Ptr [SI], Not 1 + + Jmp MixSamplesEnd +; Cmp MixMode, 8 ; Is it volume ramping? +; JB MixSamplesEnd + +MixSamples3: + Test CL, 20h ; New freq? + JZ MixSamples5 + + Mov AX, [SI+10h] + Mov DX, [SI+12h] + Mov BX, MixSpeed + Cmp DX, BX + JAE MixSamplesHandleError + + Div BX + ShL EAX, 16 + Xor AX, AX + Div BX + Mov STEPVALUE, EAX + +MixSamples4: + Test CH, 1 + JZ MixSamples5 + + Mov DWord Ptr [SI+1Ch], 0 ; Current Volume = 0 + ; for volume sliding. +MixSamples5: + Test CX, 8440h ; New volume or panning? + JZ MixSamplesMix + + Xor AX, AX + Test CH, 8 ; Muted? + JNZ MixModeCommon + + Mov BX, MixMode + Add BL, Stereo + Add BX, BX + Jmp [CS:MixModeTable+BX] + +Mix0Mode: ; 16-bit mixing, no interpolation +Mix0ModeMono: ; and 16-bit mixing, interpolation + Mov AL, [SI+20h] + ShR AL, 1 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 30 ; Use left only-mixing for mono + Jmp MixModeCommon + +Mix0ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix0ModeSurround + + Mul Byte Ptr [SI+20h] ; Final volume + Add AX, 64 + ShR AX, 7 + Mov [SI+0Ch], AX ; Store into right volume + + Mov AL, 64 + Sub AL, [SI+37h] + Mul Byte Ptr [SI+20h] + Add AX, 64 + ShR AX, 7 + Mov [SI+0Eh], AX ; Left volume + + Mov CH, AL ; CH = left volume + Mov CL, [SI+0Ch] ; CL = right volume + Mov AX, 0 + + Test CX, CX + JZ MixModeCommon + + Mov AL, 30 ; Left only... + Test CL, CL + JZ MixModeCommon + + Mov AL, 60 + Test CH, CH + JZ MixModeCommon + + Mov AL, 90 + Cmp CL, CH + JZ MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix0ModeSurround: + Mov AL, [SI+20h] + ShR AL, 2 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 150 ; Surround + Jmp MixModeCommon + +Mix6ModeMono: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 8 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Test AX, AX + JZ MixModeCommon + Mov AX, 30 + Jmp MixModeCommon + +Mix6ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix6ModeSurround + + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Ch], AX ; Store into right volume + Mov BX, AX + ShL EAX, 16 + + Mov AL, 64 ; Do left volume + Sub AL, [SI+37h] ; AL = 64-FinalPan + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Eh], AX + + Mov ECX, EAX + + ; BX = right volume + ; CX = Left volume + Mov AX, 0 + Test ECX, ECX + JZ MixModeCommon + + Mov AL, 30 + Test BX, BX + JZ MixModeCommon + + Mov AL, 60 + Test CX, CX + JZ MixModeCommon + + Mov AL, 90 + Cmp CX, BX + JE MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix6ModeSurround: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 9 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + JZ MixModeCommon + Mov AX, 150 + Jmp MixModeCommon + +MixModeCommon: ; Requires AX = 30/60/90 etc. depending + ; On mixing mode type. + ; This will add 180 for 16-bit, + ; And sort out loop types. + Mov BL, [SI+0Ah] + Test Byte Ptr [SI+18h], 2 ; 16 bit? + JZ MixModeCommon1 + + Add AX, 180 + +MixModeCommon1: + Cmp BL, 8 + JB MixModeCommon3 ; No loop + JE MixModeCommon2 ; Forwards loop + + Add AX, 10 + +MixModeCommon2: + Add AX, 10 + +MixModeCommon3: + Add AX, Offset MixFunctionTables + Add AX, MixModeOffset + Mov [SI+8], AX ; Offset... + +MixSamplesMix: + Mov BX, [SI+8] ; BX = offset into + Mov EAX, [CS:BX+2] + Mov DWord Ptr PreMixFunction, EAX + Mov EAX, [CS:BX+6] + Mov DWord Ptr MixFunctionSeparateBackwards, EAX + + Mov AX, BytesToMix + Mov MixBlockSize, AX + Mov MixBufferOffset, MIXTABLESIZE + + Mov EAX, CURRENTPOSITION + Mov OLDPOSITION, EAX + + Call Word Ptr [CS:BX] + + And Word Ptr [SI], 0111100010001101b + Jmp MixSamplesEnd + +MixSamplesHandleError: + Mov Word Ptr [SI], 200h + + Test Byte Ptr [SI+3Ah], 80h + JNZ MixSamplesEnd + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Turn off channel + +MixSamplesEnd: + Pop CX + +MixSamplesEnd2: + Add SI, 128 + Dec CX + JNZ MixSamples2 + + Ret + +EndP MixSamples + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WSSIRQHandler + + PushAD + Push DS + Push ES + + ClD + + Mov AX, CS + Mov DS, AX + Assume DS:Driver + + Mov DX, [BasePort] + Add DX, 2 + In AL, DX + Test AL, 1 + JZ WSSAckIRQ2 + + Xor AL, AL + Out DX, AL + +WSSAckIRQ2: + Mov AL, 20h + Cmp IRQ, 8 + JB WSSAckIRQ1 + + Out 0A0h, AL + +WSSAckIRQ1: + Out 20h, AL + + Mov AX, MixBufferPos + Mov BX, AX + Mul DMASize + Cmp AX, DMABUFFERLENGTH + JB WSSIRQHandler2 + + Xor AX, AX + Xor BX, BX + +WSSIRQHandler2: + Inc BX + Mov MixBufferPos, BX + + CLD + + + ; OK... time to get next block + ; Check whether stereo thing is on.. + ; + LES DI, [ActualDMAPtr] + Add DI, AX + + Mov BX, DMASize ; BX = bytes required + ShR BX, 1 + ; BX = samples required + Mov BP, 8 ; Skip for mono + Mov CL, 14 ; Shift for mono + + Cmp Stereo, 0 + JE WSSIRQHandlerMono + + Mov BP, 4 ; Stereo skip value. + Dec CL + +WSSIRQHandlerMono: + Call SaveEMSPageFrame + + Cmp MixTransferRemaining, 0 + JNE WSSIRQHandler4 + Assume DS:Nothing + +WSSIRQHandler3: + Push BX + Push CX + Push BP + Push ES + Push DI + + Call Update + Call MixSamples + + Pop DI + Pop ES + Pop BP + Pop CX + Pop BX + +WSSIRQHandler4: + Mov DS, MixSegment + Mov SI, MixTransferOffset + Mov DX, BX ; DX = samples to transfer + Cmp DX, MixTransferRemaining + JBE WSSIRQHandler5 + + Mov DX, MixTransferRemaining + +WSSIRQHandler5: + Push DX + Cmp CS:Filter, 1 + JB WSSIRQHandler6 + JE WSSIRQHFilter + + Cmp CS:Stereo, 0 + JE WSSIRQ3QFilterMono + +WSSIRQ3QFilterStereo: + Push BX + + Mov EBX, FilterValue + Mov EBP, FilterValue2 + ShR DX, 1 + +WSSIRQ3QFilterStereo1: + Mov EAX, EBX + Mov ECX, EBP + Add EAX, [SI] + Add ECX, [SI+4] + SAR EAX, 1 + SAR ECX, 1 + Add EBX, EAX + Add EBP, ECX + SAR EBX, 1 + SAR EBP, 1 + + Mov EAX, EBX + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSS3QFilterStereoClip1 + Cmp EAX, 7FFFh + JG WSS3QFilterStereoClip2 + +WSSIRQ3QFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSS3QFilterStereoClip3 + Cmp EAX, 7FFFh + JG WSS3QFilterStereoClip4 + +WSSIRQ3QFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ WSSIRQ3QFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp WSSMixTransferEnd + +WSSIRQ3QFilterMono: + Push BX + + Mov EBX, FilterValue + +WSSIRQ3QFilterMono1: + Mov EAX, EBX + Add EAX, [SI] + SAR EAX, 1 + Add EBX, EAX + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL WSS3QFilterMonoClip1 + Cmp EAX, 7FFFh + JG WSS3QFilterMonoClip2 + +WSSIRQ3QFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ WSSIRQ3QFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp WSSMixTransferEnd + +WSSIRQHFilter: + Cmp CS:Stereo, 0 + JE WSSIRQHFilterMono + +WSSIRQHFilterStereo: + Push BX + + Mov EBX, FilterValue + Mov EBP, FilterValue2 + ShR DX, 1 + +WSSIRQHFilterStereo1: + Add EBX, [SI] + Add EBP, [SI+4] + + SAR EBX, 1 + SAR EBP, 1 + + Mov EAX, EBX + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSSHFilterStereoClip1 + Cmp EAX, 7FFFh + JG WSSHFilterStereoClip2 + +WSSIRQHFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSSHFilterStereoClip3 + Cmp EAX, 7FFFh + JG WSSHFilterStereoClip4 + +WSSIRQHFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ WSSIRQHFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp WSSMixTransferEnd + +WSSIRQHFilterMono: + Push BX + + Mov EBX, FilterValue + +WSSIRQHFilterMono1: + Add EBX, [SI] + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL WSSHFilterMonoClip1 + Cmp EAX, 7FFFh + JG WSSHFilterMonoClip2 + +WSSIRQHFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ WSSIRQHFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp WSSMixTransferEnd + +WSSIRQHandler6: + Mov EAX, [SI] + SAR EAX, CL + + Cmp EAX, -8000h + JL WSSIRQHandlerClip1 + Cmp EAX, 7FFFh + JG WSSIRQHandlerClip2 + +WSSIRQHandler7: + StosW ; } Memory write + + Add SI, BP + Dec DX + JNZ WSSIRQHandler6 + +WSSMixTransferEnd: + Pop DX + + Sub MixTransferRemaining, DX ; } Memory write + Sub BX, DX + JNZ WSSIRQHandler3 + + Mov MixTransferOffset, SI ; } Memory write + + Call RestoreEMSPageFrame + + Pop ES + Pop DS + PopAD + IRet + +WSSIRQHandlerClip1: + Mov AX, 8000h + Jmp WSSIRQHandler7 + +WSSIRQHandlerClip2: + Mov AX, 7FFFh + Jmp WSSIRQHandler7 + +WSSHFilterMonoClip1: + Mov AX, 8000h + Jmp WSSIRQHFilterMono2 + +WSSHFilterMonoClip2: + Mov AX, 7FFFh + Jmp WSSIRQHFilterMono2 + +WSSHFilterStereoClip1: + Mov AX, 8000h + Jmp WSSIRQHFilterStereo2 + +WSSHFilterStereoClip2: + Mov AX, 7FFFh + Jmp WSSIRQHFilterStereo2 + +WSSHFilterStereoClip3: + Mov AX, 8000h + Jmp WSSIRQHFilterStereo3 + +WSSHFilterStereoClip4: + Mov AX, 7FFFh + Jmp WSSIRQHFilterStereo3 + +WSS3QFilterMonoClip1: + Mov AX, 8000h + Jmp WSSIRQ3QFilterMono2 + +WSS3QFilterMonoClip2: + Mov AX, 7FFFh + Jmp WSSIRQ3QFilterMono2 + +WSS3QFilterStereoClip1: + Mov AX, 8000h + Jmp WSSIRQ3QFilterStereo2 + +WSS3QFilterStereoClip2: + Mov AX, 7FFFh + Jmp WSSIRQ3QFilterStereo2 + +WSS3QFilterStereoClip3: + Mov AX, 8000h + Jmp WSSIRQ3QFilterStereo3 + +WSS3QFilterStereoClip4: + Mov AX, 7FFFh + Jmp WSSIRQ3QFilterStereo3 + +EndP WSSIRQHandler + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Add DI, Offset IRQData + Mov BX, [CS:DI] + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset WSSIRQHandler + + XChg [ES:BX], EAX + Mov OldWSSIRQHandler, EAX + + Mov AX, IMR + And AX, [DI+2] + + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Pop ES + PopAD + + Ret + +EndP SetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Mov BX, [IRQData+DI] + + Mov EAX, OldWSSIRQHandler + Mov [ES:BX], EAX + + Pop ES + PopAD + + Ret + +EndP ResetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StopWSS + + Mov DX, BasePort + + Mov AL, CODEC_INDEX_INTF + Out DX, AL + Inc DX + In AL, DX + And AL, Not INTF_PEN + Out DX, AL + + Inc DX + In AL, DX + Xor AL, AL + Out DX, AL + + Dec DX + Dec DX + + Mov AL, CODEC_INDEX_PIN + Out DX, AL + Inc DX + Xor AL, AL + Out DX, AL + + Ret + +EndP StopWSS + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StartWSS + + PushA + Push ES + Push DS + + Push CS + Pop DS + Assume DS:Driver + + ; Setup DMA + Mov BX, DMASegment + Xor AX, AX + Mov DX, DMA + Mov DI, DMABUFFERLENGTH + Call SetDMA + + LES DI, ActualDMAPtr + Xor AX, AX + Mov CX, DMABUFFERLENGTH/2 + Rep StosW + + Mov MixBufferPos, 0 + Mov MixTransferRemaining, 0 + + Mov DX, BasePort + Call PingWSS + + Mov AL, CODEC_INDEX_PIN + Out DX, AL + Inc DX + Mov AL, PIN_IEN + Out DX, AL + Dec DX + + Mov AH, WSSMixConst ; Set format/frequency + Cmp Stereo, 0 + JE StartWSS1 + + Or AH, CDF_STEREO + +StartWSS1: + Mov AL, CODEC_MCE or CODEC_INDEX_CDF + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Call WaitCodec + + Mov AL, CODEC_INDEX_CDF + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Call WaitAutoCalibration + + ; Start playback + Mov AL, CODEC_INDEX_LWR_COUNT + Out DX, AL + Inc DX + + Mov AX, DMASize + ShR AX, 1 + + Cmp Stereo, 0 + JE StartWSS2 + + ShR AX, 1 + +StartWSS2: + Dec AX + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_UPR_COUNT + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_INTF + Out DX, AL + Inc DX + In AL, DX + Or AL, INTF_PEN + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_LDC + Out DX, AL + Inc DX + In AL, DX + And AL, Not LDC_LDM + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_RDC + Out DX, AL + Inc DX + In AL, DX + And AL, Not RDC_RDM + Out DX, AL + Dec DX + + Pop DS + Pop ES + PopA + + Ret + +EndP StartWSS + Assume DS:Nothing + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov SI, Offset RelocationTable + +RelocationFix: + LodsW + Test AX, AX + JZ RelocationEnd + Mov BX, AX + Mov [BX], DS + Jmp RelocationFix + + +RelocationEnd: + Call GetEMSPageFrame + Mov EMSPageFrame, AX + + In AL, 0A1h + Mov AH, AL + In AL, 21h + Mov IMR, AX + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + Call GetWSSMixConst + + Mov AX, 2643 + Mul MixSpeed + Add AX, 0FFFFh + AdC DX, 2080 + + Mov BX, (DMABUFFERLENGTH*2)/16 + Add BX, DX + + ; Allocate MixSegment first + Mov AH, 48h + + Int 21h + JNC InitSound1 + +InitSoundNoMemory: + Mov SI, Offset WSSNoMemoryMsg + Ret + +InitSound1: + Mov MixSegment, AX + Add AX, DX + Mov DMASegment, AX + + Call SetIRQ + Call GetTempo + Call SetTempo + + Mov SI, Offset WSSMsg + + Mov AX, BasePort + Mov BX, IRQ + Mov CX, DMA + + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Call ResetIRQ + Call SetIRQ + + Mov SI, Offset ReInitMsg + Mov BX, 40 + Call SetInfoLine + + Mov AL, Stereo + Call SetStereo + + Pop ES + Pop DS + PopA + + Ret + +EndP ReInitSound + Assume DS:Nothing + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, IMR + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Mov AX, MixSegment + Test AX, AX + JZ UnInitSound1 + + Mov ES, AX + Mov AH, 49h ; Release MixSegment + Int 21h + + Call StopWSS + Call ResetIRQ + +UnInitSound1: + Ret + +EndP UnInitSound + Assume DS:Nothing + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + Ret + +EndP Poll + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Push AX + Push BX + Push DX + + Push BX + + Mov AX, MixSpeed + Mov BX, AX + Xor DX, DX + + ShL AX, 1 + RCL DX, 1 ; DX:AX = Mixspeed*2 + + ShR BX, 1 ; BX = Mixspeed/2 + + Add AX, BX + AdC DX, 0 ; DX:AX = Mixspeed*2.5 + + Pop BX ; BX = tempo + Div BX + + Mov BytesToMix, AX + + Pop DX + Pop BX + Pop AX + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + PushA + Push DS + + Mov BX, AX ; BX = MixVolume + Mov CS:MixVolume, BX + + Mov AX, CS:MixSegment + Test AX, AX + JZ SetMixVolume2 + + Mov DS, AX + + Mov CX, MIXTABLESIZE/2 + Mov SI, MIXTABLESIZE-2; Starting point - working backwards + +SetMixVolume1: + Mov AX, CX + + Dec AX ; AH = volume, AL = wave value. + Xor DX, DX + XChg AH, DL ; DL = Volume, AX = wave value + CBW + + IMul DX ; DX:AX = Volume * Wave Value + ; Ranges -8192->8128 + + IMul BX ; DX:AX = Volume * Wave Value * Mixing Volume + ; Ranges -1048576->1040384 + + Add AX, 64 + AdC DX, 0 + + ShRD AX, DX, 7 + Mov [SI], AX + Sub SI, 2 + + Loop SetMixVolume1 + +SetMixVolume2: + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS: RecalculateAllVolumes + + Pop DS + PopA + + Ret + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc RecalculateAllFrequencies + + Call GetChannelTables + +RecalculateAllFrequencies1: + Or Byte Ptr [SI], 32 + + Add SI, 128 + Dec CX + JNZ RecalculateAllFrequencies1 + + Ret + +EndP RecalculateAllFrequencies + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Mov CS:Stereo, AL + Cmp CS:MixSegment, 0 + JE SetStereo1 + + Call StopWSS + Call StartWSS + + Call RecalculateAllFrequencies + +SetStereo1: + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include loadsam.inc + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset WSS16ScreenList + + ClC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far + + Xor AH, AH + Mov AL, [CS:VolumeTable+DI] + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far + + Push DS + Push DX + + Push CS + Pop DS + Assume DS:Driver + + Mov [VolumeTable+DI], AL + + Mov DX, BasePort + + Mov AL, CODEC_INDEX_LDC + Out DX, AL + Inc DX + Mov AX, 3F3Fh + Sub AX, [Word Ptr VolumeTable] + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_RDC + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Pop DX + Pop DS + Ret + +EndP SetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. + +StopAfterPlay DW 0 +DefaultChannels DW 64 + DW 5 Dup (0) + + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/IWDRV.ASM b/SoundDrivers/IWDRV.ASM new file mode 100755 index 0000000..d29ee51 --- /dev/null +++ b/SoundDrivers/IWDRV.ASM @@ -0,0 +1,2713 @@ + + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +;************************** + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;************** Local variables **************** + +SLAVECHANNELSIZE EQU 128 +MixSpeed = 44100 + +IWReinitMsg DB "Interwave reinitialised", 0 + +IWID DB "AMD Interwave, Revision " +RevisionLetter DB " ", 13 + DB "Port ", 0FDh, "Xh, ", 0FDh, "Dk Memory", 0 + +IWID2 DB "AMD Interwave, Revision " +RevisionLetter2 DB " ", 13 + DB "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, ", 0FDh, "Dk RAM", 0 + +IWFreeMsg DB "FreeIW ", 0FDh, "Dk", 0 + +IWVolumeTable Label Word + DW 00000h, 0A0C0h, 0ABE0h, 0B250h, 0B6F0h, 0BA80h, 0BD70h, 0BFE0h + DW 0C200h, 0C3F0h, 0C5A0h, 0C720h, 0C880h, 0C9D0h, 0CB00h, 0CC10h + DW 0CD20h, 0CE10h, 0CF00h, 0CFE0h, 0D0B0h, 0D180h, 0D230h, 0D2F0h + DW 0D3A0h, 0D440h, 0D4E0h, 0D580h, 0D610h, 0D6A0h, 0D730h, 0D7B0h + DW 0D830h, 0D8B0h, 0D930h, 0D9A0h, 0DA20h, 0DA90h, 0DAF0h, 0DB60h + DW 0DBC0h, 0DC30h, 0DC90h, 0DCF0h, 0DD50h, 0DDB0h, 0DE00h, 0DE60h + DW 0DEB0h, 0DF00h, 0DF60h, 0DFB0h, 0E000h, 0E050h, 0E090h, 0E0E0h + DW 0E130h, 0E170h, 0E1C0h, 0E200h, 0E240h, 0E290h, 0E2D0h, 0E310h + DW 0E350h, 0E390h, 0E3D0h, 0E410h, 0E440h, 0E480h, 0E4C0h, 0E4F0h + DW 0E530h, 0E560h, 0E5A0h, 0E5D0h, 0E610h, 0E640h, 0E670h, 0E6B0h + DW 0E6E0h, 0E710h, 0E740h, 0E770h, 0E7A0h, 0E7D0h, 0E800h, 0E830h + DW 0E860h, 0E890h, 0E8C0h, 0E8F0h, 0E920h, 0E940h, 0E970h, 0E9A0h + DW 0E9D0h, 0E9F0h, 0EA20h, 0EA40h, 0EA70h, 0EAA0h, 0EAC0h, 0EAF0h + DW 0EB10h, 0EB40h, 0EB60h, 0EB80h, 0EBB0h, 0EBD0h, 0EBF0h, 0EC20h + DW 0EC40h, 0EC60h, 0EC90h, 0ECB0h, 0ECD0h, 0ECF0h, 0ED10h, 0ED40h + DW 0ED60h, 0ED80h, 0EDA0h, 0EDC0h, 0EDE0h, 0EE00h, 0EE20h, 0EE40h + DW 0EE60h + +OffsetTable Label Word + DW 0FFF0h, 03000h, 02800h, 02350h, 02000h, 01D60h, 01B50h, 01980h + DW 01800h, 016A0h, 01560h, 01450h, 01350h, 01260h, 01180h, 010B0h + DW 01000h, 00F40h, 00EA0h, 00E00h, 00D60h, 00CD0h, 00C50h, 00BC0h + DW 00B50h, 00AD0h, 00A60h, 009F0h, 00980h, 00920h, 008B0h, 00850h + DW 00800h, 007A0h, 00740h, 006F0h, 006A0h, 00650h, 00600h, 005B0h + DW 00560h, 00520h, 004D0h, 00490h, 00450h, 00410h, 003C0h, 00390h + DW 00350h, 00310h, 002D0h, 00290h, 00260h, 00220h, 001F0h, 001B0h + DW 00180h, 00150h, 00120h, 000F0h, 000B0h, 00080h, 00050h, 00020h + DW 00000h + + +IWMemory DW 0 ; kb of memory on IW +IWRegisterSelect DW 0 +IWVoiceSelect DW 0 +IWUpdateTimer DW 0 +IWUpdateCount DW 0 +IWMemoryFree DD 0 +IWOutputPort DW 0 +IWUpdateFlag DB 0 +IWMemorySegmented DB 0 + +IWLMCFI DW 0 +IWBankTable DB 0, 0, 0, 0 + +IWBank1 DD 0 +IWBank2 DD 0 +IWBank3 DD 0 +IWBank4 DD 0 + +OldIRQHandler DD 0 + +Convert16To8Bit DB 0 + DB 0 +Compress DB 0 + DB 0 +Stereo DB 0 + +NewIWLMCFI DW 0 + +IWDataTable DD 100 Dup (0FFFFFFFFh) +Revision DB 0 + +BankConfigs Label ; 12 configs.. +; DB 64, 64, 64, 64 ; 12 +; DB 64, 64, 0, 0 ; 11 + DB 64, 0, 0, 0 ; 10 + DB 16, 16, 16, 16 ; 9 + DB 16, 16, 0, 0 ; 8 + DB 16, 0, 0, 0 ; 7 + DB 4, 4, 16, 16 ; 6 + DB 4, 4, 16, 0 ; 5 + DB 4, 16, 16, 16 ; 4 + DB 4, 16, 0, 0 ; 3 + DB 4, 4, 4, 4 ; 2 + DB 4, 4, 0, 0 ; 1 + DB 4, 0, 0, 0 ; 0 + + +IRQData Label Word + DW 20h, 1111111111111110b ; IRQ 0 + DW 24h, 1111111111111101b ; IRQ 1 + DW 28h, 1111110111111011b ; IRQ 2 + DW 2Ch, 1111111111110111b ; IRQ 3 + DW 30h, 1111111111101111b ; IRQ 4 + DW 34h, 1111111111011111b ; IRQ 5 + DW 38h, 1111111110111111b ; IRQ 6 + DW 3Ch, 1111111101111111b ; IRQ 7 + DW 1C0h, 1111111011111011b ; IRQ 8 + DW 1C4h, 1111110111111011b ; IRQ 9 + DW 1C8h, 1111101111111011b ; IRQ 10 + DW 1CCh, 1111011111111011b ; IRQ 11 + DW 1D0h, 1110111111111011b ; IRQ 12 + DW 1D4h, 1101111111111011b ; IRQ 13 + DW 1D8h, 1011111111111011b ; IRQ 14 + DW 1DCh, 0111111111111011b ; IRQ 15 + +IMR DW 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +IWScreenList Label + DW 6 + DW Near Ptr IdleFunctionList + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr GravisHeaderLine + + DW SampleText ; 4 + + DW ConvertSampleText + DW ConvertDisabledButton ; 6 + DW ConvertEnabledButton + + DW SampleSizeText ; 8 + DW SampleSize0Button ; 9 + DW SampleSize1Button + DW SampleSize2Button + + DW DriverText + + DW 0 + +GravisHeaderLine DW 10 + DB "Interwave Driver", 0 + +DriverText DW 1 + DB 38, 48 + DB 21h + DB "Interwave Driver 1.1 for Impulse Tracker", 0 + +SampleText DW 1 + DB 3, 13 + DB 20h + DB "Sample resizing options", 0 + +ConvertSampleText DW 1 + DB 5, 15 + DB 20h + DB "Reduce 16 bit samples to 8 bit", 0 + +ConvertDisabledButton DW 2 + DW 0FFFFh, 7, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetConvert +DriverSegment1 DW 0 + DW 0 + DW Offset SetConvert +DriverSegment2 DW 0 + DB 7, 17, 20, 19, 8 + DB 0 + DB " Disabled", 0 + +ConvertEnabledButton DW 2 + DW 6, 9, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetConvert +DriverSegment3 DW 0 + DW 1 + DW Offset SetConvert +DriverSegment4 DW 0 + DB 7, 20, 20, 22, 8 + DB 0 + DB " Enabled", 0 + +SampleSizeText DW 1 + DB 5, 24 + DB 20h + DB "Sample size", 0 + +SampleSize0Button DW 2 + DW 7, 10, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetCompress +DriverSegment5 DW 0 + DW 0 + DW Offset SetCompress +DriverSegment6 DW 0 + DB 7, 26, 20, 28, 8 + DB 0 + DB " Original", 0 + +SampleSize1Button DW 2 + DW 9, 11, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetCompress +DriverSegment7 DW 0 + DW 1 + DW Offset SetCompress +DriverSegment8 DW 0 + DB 7, 29, 20, 31, 8 + DB 0 + DB " Half", 0 + +SampleSize2Button DW 2 + DW 10, 0FFFFh, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetCompress +DriverSegment9 DW 0 + DW 2 + DW Offset SetCompress +DriverSegment10 DW 0 + DB 7, 32, 20, 34, 8 + DB 0 + DB " Quarter", 0 + + +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +IdleFunctionList DD 0 + DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + + +RelocationTable Label + DW Offset DriverSegment1 + DW Offset DriverSegment2 + DW Offset DriverSegment3 + DW Offset DriverSegment4 + DW Offset DriverSegment5 + DW Offset DriverSegment6 + DW Offset DriverSegment7 + DW Offset DriverSegment8 + DW Offset DriverSegment9 + DW Offset DriverSegment10 + DW 0FFFFh + +;*********** Local functions ******************* +; +; TestIW - Checks for the presence of a IW by detecting amount of memory. +; LoadIWSample - Loads a byte to IW memory, AL = value +; LoadIWSamples - Loads ECX bytes from DS:SI to IW memory +; +;*********************************************** + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectMemory + + Push DS + Assume DS:Driver + + Push CS + Pop DS + + Mov IWMemory, 0 + + Mov DX, IWRegisterSelect + Mov AL, 52h + Out DX, AL + Inc DX + In AX, DX + Mov IWLMCFI, AX + And AX, 0FFF0h + Or AX, 0Ch ; Allow full 16MB addressing + + Mov NewIWLMCFI, AX + + Out DX, AX + + Mov CX, 256 + Xor EDI, EDI + +DetectMemory1: ; DX = BasePort+103h + Call IWSetPosition + + Xor AL, AL + Call LoadIWSample ; Write a 0 + + Add EDI, 10000h + Loop DetectMemory1 + + Mov EBX, 3 ; 4 banks, 3, 2, 1 and 0 + +DetectMemory2: + Mov EDI, EBX + ShL EDI, 22 ; DI = Bank * 4MB + Call IWSetPosition + + Mov AL, 0AAh + Mov DX, IWOutputPort + Out DX, AL + Mov AL, 055h + Out DX, AL + Call IWSetPosition + + Mov DX, IWOutputPort + + In AL, DX ; Bank doesn't exist? + Cmp AL, 0AAh + JNE DetectMemory3 + + In AL, DX + Cmp AL, 055h + JNE DetectMemory3 + + Mov CX, 64 ; Max of 4MB in 1 bank... + +DetectMemoryInnerLoop1: + Inc [IWBankTable+BX] + Inc IWMemory + + Add EDI, 10000h + Call IWSetPosition + + Mov DX, IWOutputPort + In AL, DX + Cmp AL, 0AAh + JE DetectMemory3 + + Loop DetectMemoryInnerLoop1 + +DetectMemory3: + Dec BX + JNS DetectMemory2 + + ; OK.. have checked each bank.. now to init. + Mov BL, 10 + Mov SI, Offset BankConfigs + Mov EAX, DWord Ptr IWBankTable + +DetectMemory4: + Cmp EAX, [SI] + JE DetectMemory5 + + Add SI, 4 + Dec BL + JNS DetectMemory4 + + Mov IWMemorySegmented, 1 + Jmp DetectMemory6 + +DetectMemory5: ; Set LMCI + Mov DX, IWRegisterSelect + Mov AL, 52h + Out DX, AL + Mov AX, IWLMCFI + + And AX, 0FFF0h + Or AL, BL + + Mov NewIWLMCFI, AX + + Inc DX + Out DX, AX + +DetectMemory6: + ShL IWMemory, 6 + JZ DetectMemory7 + + Pop DS + Ret + +DetectMemory7: + Pop DS + Pop AX ; Add SP, 2 + + StC + RetF + +EndP DetectMemory + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIW ; AX = baseport. + + Push AX + Push CX + Push DX + + Mov DX, AX + Add DX, 103h ; DX = IGIDXR + + Comment ~ + + Mov AL, 4Ch + Out DX, AL + Add DL, 2 + Xor AL, AL + Out DX, AL + + Push DX + Mov DX, 300h + Mov CX, 20 +ResetIW4: + In AL, DX + Loop ResetIW4 + Pop DX + + Mov AL, 1 + Out DX, AL + + Push DX + Mov DX, 300h + Mov CX, 20 +ResetIW3: + In AL, DX + Loop ResetIW3 + Pop DX + + Sub DL, 2 + + ~ + + Mov AL, 19h ; Write SGMI + Out DX, AL + + Add DL, 2 + + Mov AL, 1 + Out DX, AL ; Enhanced mode enabled. + Sub DL, 2 + + Mov AL, 99h ; Read SGMI + Out DX, AL + Add DL, 2 + In AL, DX + Sub DL, 2 + + Cmp AL, 1 + JNE ResetIW1 + + Mov AL, 53h ; LMCI + Out DX, AL + + Add DL, 2 + Mov AL, 1 + Out DX, AL ; Auto increment, DRAM, 8-bit, NoInvert + Sub DL, 2 + + ClC + Jmp ResetIW2 + +ResetIW1: + StC + +ResetIW2: + Pop DX + Pop CX + Pop AX + + Ret + +EndP ResetIW + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc TestIW + + + Call ResetIW + JC TestIW3 + + Push AX + + Mov IWMemory, 0 + + Mov DX, AX + Add DX, 103h ; DX = Select Register + + Mov CX, 256 ; Max amount is 16MB of memory + Xor BX, BX ; BX = no of 64k chunks. + +TestIW1: + ClI + + Mov AL, 44h ; IW DRAM High, 8 bit + Out DX, AL + + Add DL, 2 + Mov AX, BX ; BX = IW DRAM High + Out DX, AL + Sub DL, 2 ; DX = Select Register + + Mov AL, 43h ; IW DRAM Low, 16 bit + Out DX, AL + + Inc DX ; DX = Baseport+104h + Xor AX, AX + Out DX, AX ; Address 0 + + StI + + Add DL, 3 ; DX = Baseport+107h (DRAM I/O) + + Mov AL, 55h + Out DX, AL ; Write value 55h + Mov AL, 0AAh + Out DX, AL ; Write value 0AAh + Mov AL, CL + Out DX, AL ; Write value + + Sub DL, 3 ; DX = Baseport+104h + Xor AX, AX + Out DX, AX ; Address 0 + + Add DL, 3 ; DX = Baseport+107h + In AL, DX ; Read value.. + Cmp AL, 55h + JNE TestIW2 + + In AL, DX ; Read value.. + Cmp AL, 0AAh + JNE TestIW2 + + In AL, DX ; Read value.. + Cmp AL, CL + JNE TestIW2 + + Inc BX + Sub DL, 4 ; DX = Baseport+103h + Loop TestIW1 + +TestIW2: + Pop AX + + And BX, BX + JZ TestIW3 + + ShL BX, 6 + Mov IWMemory, BX + ClC + Ret + +TestIW3: + StC + Ret + +EndP TestIW + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc IWSetPosition ; EDI = position + + ClI + Mov DX, CS:IWRegisterSelect + Mov AL, 44h + Out DX, AL + + Add DL, 2 + SHLD EAX, EDI, 16 +; Mov EAX, EDI +; ShR EAX, 16 + Out DX, AL + Sub DL, 2 ; Select register again. + + Mov AL, 43h ; Address Low, 16 bit + Out DX, AL + Inc DX ; DX = 3x4h + + Mov AX, DI ; Memory location high + Out DX, AX ; Memory location done. + + StI + Ret + +EndP IWSetPosition + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc LoadIWSample ; AL = value + + Mov DX, CS:IWOutputPort + Out DX, AL + + Ret + +EndP LoadIWSample + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc LoadIWSamples ; Given DS:SI, ECX = count + ; EBP = step value. + + Mov DX, CS:IWOutputPort + +LoadIWSamples2: + Mov AL, [SI] + Add SI, BP + JC LoadIWSamples4 + +LoadIWSamples3: + Out DX, AL + + LoopD LoadIWSamples2 + Ret + +LoadIWSamples4: + Add ESI, 10000h + Int 3 + Jmp LoadIWSamples3 + +EndP LoadIWSamples + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Load16IWSamples ; Given DS:SI, ECX = count + ; EBP = step value. + + Add BP, BP + Dec BP + Mov BX, 1 + Xor BP, BX + Xor BX, BP + + Mov DX, CS:IWOutputPort + +Load16IWSamples1: + Xor BX, BP + Mov AL, [SI] + Add SI, BX + JC Load16IWSamples4 + +Load16IWSamples3: + Out DX, AL + + Dec ECX + JNZ Load16IWSamples1 + Ret + +Load16IWSamples4: + Add ESI, 10000h + Int 3 + Jmp Load16IWSamples3 + +EndP Load16IWSamples + +;*********** Public functions ****************** + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectIW Far + + Cmp BasePort, 0FFFFh + JE DetectIW1 + + Mov AX, BasePort + Call TestIW + JNC DetectIW3 + + Ret + +DetectIW1: + Mov AX, 210h + +DetectIW2: + Call TestIW + JNC DetectIW3 + + Add AL, 10h + Cmp AL, 60h + JBE DetectIW2 + + StC + Ret + +DetectIW3: + Mov BasePort, AX + Add AX, 102h + Mov IWVoiceSelect, AX + Inc AX + Mov IWRegisterSelect, AX + Add AL, 4 + Mov IWOutputPort, AX + + Call DetectMemory + + Mov EAX, 'Jeff' + + ClC + Ret + +EndP DetectIW + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc IWIRQOnlyHandler + + PushAD + Push DS + Push ES + + Mov AL, 20h + + Cmp CS:IRQ, 8 + JB IWIRQOnlyHandler1 + + Out 0A0h, AL + +IWIRQOnlyHandler1: + Out 20h, AL + + Mov DX, CS:BasePort + Add DL, 6 + In AL, DX + And AL, 8 + JZ IWIRQOnlyHandler2 + + Mov DX, CS:IWRegisterSelect + Mov AL, 45h + Out DX, AL + Mov AL, 0 + Add DL, 2 + Out DX, AL + Mov AL, 8 + Out DX, AL + Sub DL, 2 + + ClD + + Call SaveEMSPageFrame + Call Update + Call SetIWRegisters + Call RestoreEMSPageFrame + +IWIRQOnlyHandler2: + Pop ES + Pop DS + PopAD + + IRet + +EndP IWIRQOnlyHandler + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc IWIRQHandler ; IRQ Handler has to + ; 1) Update IW registers + ; 2) Update song position + Push AX + Push DS + + Mov AX, IWUpdateTimer + Add IWUpdateCount, AX + JC IWIRQHandler1 + + Mov AL, 20h + Out 20h, AL + Jmp IWIRQHandler2 + +IWIRQHandler1: + PushF + Call [OldIRQHandler] + +IWIRQHandler2: + Xor IWUpdateFlag, 1 + JZ IWIRQHandlerEnd + + PushAD + Push ES + + ClD + + Call SaveEMSPageFrame + Call Update ; Returns DS:SI, CX + Call SetIWRegisters + Call RestoreEMSPageFrame + + Pop ES + PopAD + +IWIRQHandlerEnd: + Pop DS + Pop AX + IRet + +EndP IWIRQHandler + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIWVolume ; BX = new volume + + ; To do: + ; 1) Set ramp start + ; 2) Set ramp end + ; 3) Set current volume + ; 4) Start ramp + ; 5) Save new volume. + + Push BX + Push CX + + Mov AL, 0Dh + Out DX, AL + + Mov AL, 3 ; Stop Ramp! + Add DL, 2 + Out DX, AL + Sub DL, 2 + + Add BX, BX + Mov CX, [CS:IWVolumeTable+BX] ; CX = new volume + Mov BX, [SI+2] + Add BX, BX + Mov BX, [CS:IWVolumeTable+BX] ; BX = old volume + + Cmp BX, CX + JNE SetIWVolume2 + + Mov AL, 89h + Out DX, AL + Inc DX + In AX, DX + Dec DX + + Mov BX, AX ; BX = old volume + +SetIWVolume2: + + Push BX ; Old volume on stack + + Xor AH, AH ; Ramp up + Cmp CX, BX + JE SetIWVolume4 + JA SetIWVolume1 + + XChg BX, CX + Mov AH, 40h ; Ramp down + +SetIWVolume1: + Mov AL, 6 ; Ramp rate + Out DX, AL + + Mov AL, 32 ; Ramp rate + Add DL, 2 + Out DX, AL + Sub DL, 2 + + Mov AL, 7 ; Ramp start + Out DX, AL + + Mov AL, BH + Add DL, 2 + Out DX, AL + Sub DL, 2 + + Mov AL, 8 ; Ramp end + Out DX, AL + + Mov AL, CH + Add DL, 2 + Out DX, AL + Sub DL, 2 + + Mov AL, 9 + Out DX, AL + + Pop BX ; BX = old volume + XChg BX, AX + + Inc DX + Out DX, AX + Dec DX + + Mov AL, 0Dh ; Ramp control + Out DX, AL + + Mov AL, BH + Add DL, 2 + Out DX, AL + Sub DL, 2 + +SetIWVolume5: + Pop CX + Pop BX + + Mov [SI+2], BX + + Ret + +SetIWVolume4: +; Mov AL, 0Dh ; Volume Ramp. +; Out DX, AL +; +; Mov AL, 3 +; Add DL, 2 +; Out DX, AL +; Sub DL, 2 + + Mov AL, 9 + Out DX, AL + + Pop AX ; AX = old volume + + Inc DX + Out DX, AX + Dec DX + + Jmp SetIWVolume5 + +EndP SetIWVolume + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc IWGetAddress ; Given EAX + + Push CX + + Mov CL, CS:Compress + ShR EAX, CL + + Pop CX + Add EAX, [CS:IWDataTable+BX] + ShL EAX, 9 + And EAX, 7FFFFFFFh + + Ret + +EndP IWGetAddress + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIWRegisters ; Given DS:SI, CX + + Mov ES, CS:SongDataArea + + Push CX + Push SI + + Xor AX, AX + +GetOffsetLoop: + Push AX + Push CX + + Mov DX, IWVoiceSelect + Out DX, AL ; OK.. now to play with this + ; voice. + Inc DL ; DX = select rego + + Mov BX, [SI] + Test BH, 2 + JZ GetOffsetLoop2 + + Mov BX, 200h + Mov [SI], BX + +GetOffsetLoop2: + Test BL, 1 ; Channel not on! + JZ GetOffsetLoop1 + Test BH, 1 + JZ GetOffsetLoop3 ; Prev 1. + + Xor BX, BX + Call SetIWVolume + + Jmp GetOffsetLoop1 + +GetOffsetLoop3: + Mov EAX, [SI+4Ch] + Mov [SI+2Ch], EAX + + Mov AL, 8Ah + Out DX, AL + + Inc DX + In AX, DX + Dec DX + + And AH, 7Fh + ShL EAX, 16 ; Load high part of EAX + + Mov AL, 8Bh + Out DX, AL + Inc DX + In AX, DX + ; EAX = 000OOOOO OOOOOOOO OOOOOOOF FFFFFFFF + ; Need: 00000000 0000OOOO OOOOOOOO OOOOOOOO + + ShR EAX, 9 + + MovZX EBX, Byte Ptr [SI+36h] + Mov EBX, [CS:IWDataTable+EBX*4] + And EBX, 03FFFFFh + Sub EAX, EBX + Push CX + + Mov CL, CS:Compress + ShL EAX, CL + + Pop CX + Mov [SI+4Ch], EAX + +GetOffsetLoop1: + Add SI, SLAVECHANNELSIZE + + Pop CX + Pop AX + + Inc AX + Dec CX + JNZ GetOffsetLoop + + Pop SI + Pop CX + + Xor AX, AX + +SetIWRegisters1: + Push AX + Push CX + + Mov DX, IWVoiceSelect + Out DX, AL ; OK.. now to play with this + ; voice. + Mov CX, [SI] ; CX = flags. + Inc DL ; DX = select rego + + Test CH, 1 + JZ SetIWRegisters21 + + Mov AL, [SI+36] + Cmp AL, [SI+4] + JE SetIWRegisters21 + + Xor AL, AL + Out DX, AL + + Mov AL, 3 + Add DL, 2 + Out DX, AL + Sub DL, 2 + +SetIWRegisters21: + Test CL, 32 ; Frequency change + JZ SetIWRegisters7 + + Push DX + + Mov EAX, [SI+10h] ; EAX = freq. + + Push CX + Mov CL, CS:Compress + ShR EAX, CL + Pop CX + + Xor EDX, EDX + Mov EBX, MixSpeed + + Div EBX ; EAX = I portion. + + Test EAX, Not 63 + JNZ SetIWRegisters6 + + Push EAX + + Xor EAX, EAX + Div EBX + + Pop EBX ; EBX:EAX = IIII FFFF etc. + + SHRD EAX, EBX, 6 + + ; Have: IIIIIIII IIIIIIII FFFFFFFF FFFFFFFF + ; Req: IIIIIIFF FFFFFFF0 + + Pop DX + Mov AL, 1 + Out DX, AL + + ShR EAX, 16 + AdC AX, 0 + SBB AX, 0 ; Just in case! + + Inc DX + Out DX, AX + Dec DX + + Jmp SetIWRegisters7 + +SetIWRegisters6: + Mov CH, 2 ; Signify to turn off channel + Pop DX + +SetIWRegisters7: + MovZX BX, Byte Ptr [SI+36h] ; BX = sample number. + Cmp BL, 99 + JA SetIWRegisters20 + + ShL BX, 2 ; IWDataTable+BX = position + + Cmp DWord Ptr [CS:IWDataTable+BX], 0FFFFFFFFh + JNE SetIWRegisters10 + +SetIWRegisters20: + Mov CH, 2 + Jmp SetIWRegisters9 + +SetIWRegisters10: + Test CH, 5 ; Loop changed?!??!? + JZ SetIWRegisters8 + + Mov AL, 3 ; Starting location low. + Out DX, AL + + Mov EAX, [SI+40h] + Call IWGetAddress + + ; Reqd: .OOOOOOO OOOOOOOO OOOOOOOI III..... + + Inc DX + Out DX, AX + Dec DX + + Mov AL, 2 ; Starting location high + Out DX, AL + + ShR EAX, 16 + Inc DX + Out DX, AX + Dec DX + + ; Ending location... + Mov AL, 5 ; Ending location low + Out DX, AL + + Mov EAX, [SI+44h] + Call IWGetAddress + + Inc DX + Out DX, AX + Dec DX + + Mov AL, 4 ; Ending location high + Out DX, AL + + SHR EAX, 16 + Inc DX + Out DX, AX + Dec DX + +SetIWRegisters8: + Test CH, 1 ; Do Current position? + JZ SetIWRegisters9 + + Xor AL, AL + Out DX, AL + + Mov AL, 3 + Add DL, 2 + Out DX, AL + Sub DL, 2 + + Mov AL, 9 + Out DX, AL + Xor AX, AX + Inc DX + Out DX, AX + Dec DX + + Mov AL, 10h + Out DX, AL + Add DL, 2 + Mov AL, Byte Ptr [CS:IWDataTable+BX+2] + ShR AL, 6 + Out DX, AL + Sub DL, 2 + + Mov AL, 0Bh ; Current location LOW + Out DX, AL + + Mov EAX, [SI+4Ch] + Mov [SI+2Ch], EAX + + ; EAX = OOOOOOOO OOOOOOOO OOOOOOOO OOOOOOOO + ; Req: xOOOOOOO OOOOOOOO OOOOOOOF FFFFFFFF + Call IWGetAddress + + Mov DI, AX + + Inc DX + Out DX, AX + Dec DX + + Mov AL, 0Ah ; Current location HIGH + Out DX, AL + + SHR EAX, 16 + Inc DX + Out DX, AX + Dec DX + + Mov AL, 0Bh + Out DX, AL + + Mov AX, DI + Inc DX + Out DX, AX + Dec DX + +SetIWRegisters9: + Test CL, 64 ; New volume?? + JZ SetIWPan + +SetIWRegisters23: + Xor BX, BX + Test CH, 8 + JNZ SetIWRegistersMuted + + Mov BL, Byte Ptr [SI+20h] ; BL = volume, 0->128 + +SetIWRegistersMuted: + Call SetIWVolume + +SetIWPan: + Test CH, 128 ; New pan?? + JZ SetIWRegisters5 + + Xor BH, BH + + Test CS:Stereo, 1 + JZ SetIWRegisters3 + + Mov BL, [SI+37h] + Cmp BL, 100 + JNE SetIWRegisters4 + +SetIWRegisters3: + Mov BL, 32 ; Surround goes to mono :( + +SetIWRegisters4: + Add BX, BX ; BX = offset into IWTable + + Test CH, 1 + JZ IWSetPan1 + + Mov AL, 0Ch ; Right offset + Out DX, AL + Inc DX + Mov AX, [CS:OffsetTable+BX] + Out DX, AX + Dec DX + + Neg BX + + Mov AL, 13h ; Left offset final + Out DX, AL + Inc DX + Mov AX, [CS:OffsetTable+128+BX] + Out DX, AX + Dec DX + + Neg BX + +IWSetPan1: + Mov AL, 1Bh ; Right offset final + Out DX, AL + Inc DX + Mov AX, [CS:OffsetTable+BX] + Out DX, AX + Dec DX + + Neg BX + + Mov AL, 1Ch ; Left offset final + Out DX, AL + Inc DX + Mov AX, [CS:OffsetTable+128+BX] + Out DX, AX + Dec DX + +SetIWRegisters5: + ; Now for control register. + ; If CH | 2, then turn rego OFF + ; If CH | 5, then turn rego ON + ; If CL | 1, then check channel + Test CH, 2 + JNZ SetIWRegisters11 + + Test CH, 5 + JNZ SetIWRegisters12 + + Test CL, 1 + JZ SetIWRegisters13 + + Mov AL, 80h ; Read voice control + Out DX, AL + + Add DL, 2 + In AL, DX + Sub DL, 2 + + Test AL, 1 + JZ SetIWRegisters13 + + Xor BX, BX + Call SetIWVolume + + Jmp SetIWRegisters14 + +SetIWRegisters11: ; Turn off. + Mov Byte Ptr [SI+4], 0FFh + + Xor BX, BX + Call SetIWVolume + + Xor AL, AL + Out DX, AL + Mov AL, 2 + Add DL, 2 + Out DX, AL + Sub DL, 2 + + Mov AL, 15h + Out DX, AL + + Add DL, 2 ; Synthesizer Mode select + Mov AL, 34 ; Offset enable, enable voice + Out DX, AL + Sub DL, 2 + + +SetIWRegisters14: + Test CL, 1 + JZ SetIWRegisters13 + + Xor CX, CX ; Turn off channel + Test Byte Ptr [SI+3Ah], 80h + JNZ SetIWRegisters13 + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Signify channel off + + Jmp SetIWRegisters13 + +SetIWRegisters12: ; Turn on + Mov AL, [SI+36] + Mov [SI+4], AL + + Mov AL, 15h + Out DX, AL + + Add DL, 2 ; Synthesizer Mode select + Mov AL, 32 ; Offset enable, enable voice + Out DX, AL + Sub DL, 2 + + Xor AL, AL + Out DX, AL + + Mov AL, [SI+0Ah] + + Cmp CS:Convert16To8Bit, 0 + JNZ SetIWRegistersNo16Bit + + Mov AH, [SI+18h] ; 16 bit? + Add AH, AH + Or AL, AH + +SetIWRegistersNo16Bit: + Test CL, 1 + JNZ SetIWRegisters15 + + Mov AL, 2 + Xor CX, CX + +SetIWRegisters15: + Add DL, 2 + Out DX, AL + +SetIWRegisters13: + And CX, 0111100010011111b ; Turns off: + ; 1) Freq & vol recalc + ; 2) New note/note stop/loop cha + + Mov [SI], CX + + Add SI, SLAVECHANNELSIZE + + Pop CX + Pop AX + + Inc AX + Dec CX + JNZ SetIWRegisters1 + + Ret + + +EndP SetIWRegisters + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + Mov SI, Offset RelocationTable + +Relocation1: + LodsW + Cmp AX, 0FFFFh + JE RelocationEnd + + Mov BX, AX + Mov [BX], CS + Jmp Relocation1 + +RelocationEnd: ; OK... disable the IW Line In + ; & Enable Line Out + ; SetupMIDI + Mov DX, BasePort + Inc DH + Mov AL, 0FFh + Out DX, AL + Mov AL, 0FCh + Out DX, AL + + ; Setup the rest of it. + Mov DX, BasePort + Mov AL, 1 + Out DX, AL + + Mov DX, IWRegisterSelect + Mov AL, 0Eh + Out DX, AL ; DX = BasePort+103h + + Add DL, 2 ; DX = BasePort+105h + Mov AL, 0CDh + Out DX, AL ; Full mixing rate + + Mov CX, 32 + Sub DL, 3 + +IWResetVoice1: + Mov AL, CL + Dec AL + Out DX, AL + + Inc DX ; DX = BasePort + 103h + Xor AL, AL ; Voice control register, 8 bit + Out DX, AL + + Add DL, 2 + Mov AL, 3 + Out DX, AL ; Stop voice + Sub DL, 2 + + Mov AL, 0Dh ; Volume Ramp. + Out DX, AL + + Mov AL, 3 + Add DL, 2 + Out DX, AL + Sub DL, 2 + + Mov AL, 6 ; Ramp rate + Out DX, AL + + Mov AL, 32 ; Ramp rate + Add DL, 2 + Out DX, AL + Sub DL, 2 + + Mov AL, 9 ; Volume register, 16 bit + Out DX, AL + + Inc DX + Xor AX, AX + Out DX, AX ; No volume + Dec DX + + Mov AL, 15h + Out DX, AL + + Add DL, 2 ; Synthesizer Mode select + Mov AL, 32 ; Offset enable, enable voice + Out DX, AL + + ClI + Sub DL, 3 ; DX = BasePort + 102h = Voice select. + + Loop IWResetVoice1 + + Inc DL + Mov AL, 5Bh + Out DX, AL + Add DL, 2 + In AL, DX + Sub DL, 2 + Shr AL, 4 ; AL = revision number + + Add AL, 'A' + Mov Revision, AL +; Cmp AL, 'C' +; JE InitSound_IW2 + +; Mov OffsetTable, Offset IWOffsetTable2 + +InitSound_IW2: + Cmp CS:IRQ, 0FFFFh + JE InitSound_IW1 + + Mov AX, BasePort + Call ResetIW + + In AL, 0A1h + Mov AH, AL + In AL, 21h + Mov IMR, AX + + ; Set IRQ + Mov BX, IRQ + ShL BX, 2 ; BX points to offset in IRQData + + Xor DI, DI + Mov ES, DI + Mov DI, [BX+IRQData] + + And AX, [BX+IRQData+2] + + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset IWIRQOnlyHandler + + XChg [ES:DI], EAX + Mov OldIRQHandler, EAX + + StI + + Mov DX, BasePort + Mov AL, 9 + Out DX, AL + + Call GetTempo + Call SetTempo + Call ResetMemory + + Mov AL, Revision + Mov RevisionLetter2, AL + + Mov AX, BasePort + Mov BX, IRQ + Mov CX, IWMemory + + Mov SI, Offset IWID2 + + ClC + Ret + +InitSound_IW1: + Mov AL, 4Ch + Out DX, AL + Add DL, 2 + Mov AL, 3 + Out DX, AL + + Mov AL, 34h ; Program IRQ 0. LSB&MSB, Rate gen + Out 43h, AL + + Call GetTempo + Call SetTempo + Call ResetMemory + + Mov DX, BasePort + Mov AL, 1 + Out DX, AL + + Xor AX, AX + Mov ES, AX ; ES = 0 + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset IWIRQHandler + + ClI + + XChg DWord Ptr [ES:20h], EAX ; Clock tick + Mov OldIRQHandler, EAX + + StI + + Mov AL, Revision + Mov RevisionLetter, AL + + Mov AX, BasePort + Mov BX, IWMemory + Mov SI, Offset IWID + + ClC + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + Push CS + Pop DS + Mov SI, Offset IWReinitMsg + Mov BX, 40 + Call SetInfoLine + + Mov BX, CS:IRQ + Cmp BX, 0FFFFh + JE ReInitSound1 + + Mov AX, CS:IMR + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + ShL BX, 2 + Xor DI, DI + Mov ES, DI + Mov DI, [CS:BX+IRQData] + Mov EAX, CS:OldIRQHandler + + Mov [ES:DI], EAX + + Jmp ReInitSound2 + +ReInitSound1: + Mov AL, 34h + Out 43h, AL + + Xor AX, AX + Out 40h, AL + Out 40h, AL + + Mov ES, AX + Mov EAX, OldIRQHandler + Mov [ES:20h], EAX + +ReInitSound2: + Mov DX, IWRegisterSelect + Mov AL, 52h + Out DX, AL + Inc DX + Mov AX, NewIWLMCFI + Out DX, AX + + Jmp RelocationEnd + +EndP ReInitSound + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Mov AX, BasePort + Call ResetIW + + Mov DX, BasePort + Inc DH + Mov AL, 0FFh + Out DX, AL ; Stop MIDI + + Mov CX, 32 + Mov DX, CS:IWVoiceSelect + +IWResetVoice2: + Mov AL, CL + Dec AL + Out DX, AL + + Inc DX ; DX = BasePort + 103h + Xor AL, AL ; Voice control register, 8 bit + Out DX, AL + + Add DL, 2 + Mov AL, 3 + Out DX, AL ; Stop voice + Sub DL, 2 + + Mov AL, 0Dh ; Volume Ramp. + Out DX, AL + + Mov AL, 3 + Add DL, 2 + Out DX, AL + Sub DL, 2 + + Mov AL, 9 ; Volume register, 16 bit + Out DX, AL + + Inc DX + Xor AX, AX + Out DX, AX ; No volume + Dec DX + + Mov AL, 15h + Out DX, AL + + Add DL, 2 + Mov AL, 2 + Out DX, AL ; Deactivate voice + + ClI + Sub DL, 3 ; DX = BasePort + 102h = Voice select. + + Loop IWResetVoice2 + +; Inc DL +; Mov AL, 4Ch +; Out DX, AL +; Xor AL, AL +; Add DL, 2 +; Out DX, AL + + Mov BX, CS:IRQ + Cmp BX, 0FFFFh + JE UnInitSound1 + + Mov AX, CS:IMR + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + ShL BX, 2 + Xor DI, DI + Mov ES, DI + Mov DI, [CS:BX+IRQData] + Mov EAX, CS:OldIRQHandler + + Mov [ES:DI], EAX + + Jmp UnInitSound2 + +UnInitSound1: + Mov AL, 34h + Out 43h, AL + + Xor AX, AX + Out 40h, AL + Out 40h, AL + + Mov ES, AX + Mov EAX, OldIRQHandler + Mov [ES:20h], EAX + +UnInitSound2: + Mov DX, IWRegisterSelect + Mov AL, 52h + Out DX, AL + Mov AX, IWLMCFI + Inc DX + Out DX, AX + + Ret + +EndP UnInitSound + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + ClI + +Poll1: + Call [CS:UARTBufferEmpty] + JNC MIDIEnd + + Mov DX, [CS:BasePort] + Inc DH + In AL, DX + Test AL, 1 + JZ MIDIEnd + + Inc DX + In AL, DX + Cmp AL, 0F0h + JAE MIDIEnd + + Call [CS:UARTSend] + Jmp Poll1 + +MIDIEnd: + StI + + Ret + +EndP Poll + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UARTOut + + Push DX + Push AX + + Mov DX, [CS:BasePort] + Inc DH + +UARTOut1: + In AL, DX + Test AL, 2 + JZ UARTOut1 + + Pop AX + Inc DX + + Out DX, AL + + Pop DX + + Ret + +EndP UARTOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +InterpretState DB 0 + +Proc SendUARTOut Far ; Local interpreter activated with 0F0h 0F0h. + + Mov AH, CS:InterpretState + Cmp AH, 2 + JB SendUARTOut1 + +; In interpreter. + JE SendUARTOut3 + +; Have InterpretType, now get parameter, then return to normal. + + Mov CS:InterpretState, 0 + +SendUARTOut4: + Ret + +SendUARTOut3: + Jmp SendUARTOutStateInc + +SendUARTOut1: + Cmp AL, 0F0h + JNE SendUARTOut2 + +SendUARTOutStateInc: + Inc CS:InterpretState + Ret + +SendUARTOut2: + Test AH, AH + JZ SendUARTOutEnd + + Push AX + Mov AL, 0F0h + Call UARTOut + Pop AX + Mov CS:InterpretState, 0 + +SendUARTOutEnd: + Call UARTOut + Ret + +EndP SendUARTOut + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far ; BX = tempo... + + Push AX + Push BX + Push DX + + Cmp CS:IRQ, 0FFFFh + JE SetTempo1 + + ShL BX, 8 + Mov DX, 1Eh + Mov AX, 8480h + Div BX + Neg AL + + Mov AH, AL + + Mov DX, CS:IWRegisterSelect + + Mov AL, 47h + Out DX, AL + Add DL, 2 + Mov AL, AH + Out DX, AL ; Set Timer control register 2 + Sub DL, 2 + + Mov AL, 45h + Out DX, AL + Add DL, 2 + Mov AL, 8 + Out DX, AL +; Sub DL, 2 + + Mov DX, CS:BasePort + Add DL, 8 + Mov AL, 4 + Out DX, AL + + Inc DL + Mov AL, 2 + Out DX, AL + + Jmp SetTempo2 + +SetTempo1: + ; Frames per second = 2 * (0.4*Tempo) + Mov AX, 0C214h + Mov DX, 16h ; Ticks = (1193181/(2*0.4))/Tempo + Div BX + + ; AX contains counter. + Mov IWUpdateTimer, AX + + Out 40h, AL ; Timer IRQ. + Mov AL, AH + Out 40h, AL + +SetTempo2: + Pop DX + Pop BX + Pop AX + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + Ret + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Mov CS:Stereo, AL + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc LoadSample Far + + PushAD + Push DS + Push ES + Push FS + + Mov FS, CS:SongDataArea + Mov BP, AX + Dec BP + Add BP, BP + Mov BP, [FS:64912+BP] + + Xor CX, CX ; From the start of the sample.. + Call GetSampleLocation ; Returns DS:ESI, ECX = length + JC Music_IWLoadSampleEnd + + Mov BL, [FS:BP+12h] + Test BL, 16 + JZ Music_IWLoadSample12 + + Cmp ECX, [FS:BP+38h] + JBE Music_IWLoadSample12 + + Mov ECX, [FS:BP+38h] + Test BL, 32 + JZ Music_IWLoadSample12 + + Cmp ECX, [FS:BP+44h] + JAE Music_IWLoadSample12 + + Mov ECX, [FS:BP+44h] + +Music_IWLoadSample12: + Mov EBX, ECX + Mov CL, CS:Compress + Mov EDX, 1 + ShR EBX, CL + ShL EDX, CL ; EDX = step value. + + Mov ECX, EBX + + ; Now find location to put it in + + Dec AX ; AX = sample number + Push AX ; AX = sample number (0 based) + + And EAX, 0FFh + Mov DWord Ptr [CS:IWDataTable+4*EAX], 0FFFFFFFFh + + Add ECX, 2 + + Cmp IWMemorySegmented, 0 + JNE Music_IWLoadSegmented1 + + Mov EAX, IWMemoryFree + + Test Byte Ptr [FS:BP+12h], 2 ; 16 bit?? + JZ Music_IWLoadSamples13 + + Cmp CS:Convert16To8Bit, 0 + JNZ Music_IWLoadSamples5 + + Sub EAX, 1 + JC Music_IWLoadSampleWarning + And EAX, Not 1 ; For alignment + Add ECX, ECX + Jmp Music_IWLoadSamples13 + +Music_IWLoadSamples5: + Inc ESI + Add EDX, EDX ; Step value. + +Music_IWLoadSamples13: + Cmp ECX, EAX + JBE Music_IWLoadSample2 + + ; Warning msg here. +Music_IWLoadSampleWarning: + Pop AX + ClC + Jmp Music_IWLoadSampleEnd + +Music_IWLoadSample3: + StC + +Music_IWLoadSampleEnd: + Pop FS + Pop ES + Pop DS + PopAD + + Ret + +Music_IWLoadSegmented1: + Test Byte Ptr [FS:BP+12h], 2 ; 16 bit?? + JZ Music_IWLoadSegmented3 + + Cmp CS:Convert16To8Bit, 0 + JNZ Music_IWLoadSegmented2 + + Add ECX, ECX + + ; Check each of 4 banks... + Xor BX, BX + +Music_Load16BitSegment1: + Mov EAX, [IWBank1+BX] + And EAX, Not 1 ; For alignment + Cmp ECX, EAX + JBE Music_LoadSegment2 + +Music_Load16BitSegment2: + Add BX, 4 + Cmp BX, 16 + JB Music_Load16BitSegment1 + Jmp Music_IWLoadSampleWarning + +Music_LoadSegment2: + Sub EAX, ECX + Mov [IWBank1+BX], EAX + ShL EBX, 20 + Add EBX, EAX + Jmp LoadIWSampleChain + +Music_IWLoadSegmented2: + Inc ESI + Add EDX, EDX ; Step value. + +Music_IWLoadSegmented3: + Xor BX, BX + +Music_Load8BitSegment1: + Mov EAX, [IWBank1+BX] + Cmp ECX, EAX + JBE Music_LoadSegment2 + + Add BX, 4 + Cmp BX, 16 + JB Music_Load8BitSegment1 + Jmp Music_IWLoadSampleWarning + +Music_IWLoadSample2: ; EAX = number of bytes free. + ; DS:SI = sample. + ; ECX = number of bytes of memory + ; ES:DI = num bytes free ptr + ; BP = sample number. + + ; Location = MaxMem - DX:AX + ; = -(DX:AX - IWBanks*4:0) + MovZX EBX, CS:IWMemory + ShL EBX, 10 + ; BX = bytes avail. + Sub EBX, EAX + Sub EAX, ECX + Mov IWMemoryFree, EAX + +LoadIWSampleChain: + Pop DI ; DI = sample number + + ShL DI, 2 + + Cmp CS:Convert16To8Bit, 0 + JNZ LoadIWForced8Bit + + Test Byte Ptr [FS:BP+12h], 2 + JNZ Music_IWLoad16BitSample + +LoadIWForced8Bit: + Push EBX + Inc EBX + Mov [CS:IWDataTable+DI], EBX ; Store pointer + + Mov ES, CS:SongDataArea + Pop EDI ; EDI = location in IW mem + + Sub ECX, 2 + ; EDI = location in IW mem + ; DS:SI = sample data + ; ECX = length. + ; EDX = step value. + ClI + + Push BP + + Mov EBP, EDX + + Call IWSetPosition + + Mov AL, [DS:SI+BP] + Call LoadIWSample + Call LoadIWSamples + + Mov BH, AL + + Pop BP + + Mov AL, [FS:BP+12h] + Test AL, 16 + JZ Music_IWLoadSample10 + + Mov ESI, [FS:BP+34h] + Test AL, 64 + JZ Music_IWLoadSample11 + + Mov ESI, [FS:BP+38h] + Sub ESI, 2 + AdC ESI, 0 + + Mov EAX, Not 0 + Mov CL, CS:Compress + ShL EAX, CL + And ESI, EAX + +Music_IWLoadSample11: + Test Byte Ptr [FS:BP+12h], 2 + JZ Music_IWLoadSample6 + + Add ESI, ESI + Inc SI + +Music_IWLoadSample6: + Int 3 + + Mov BH, [SI] + +Music_IWLoadSample10: + Mov AL, BH + Call LoadIWSample + + StI + Jmp Music_IWLoadSample3 ; Return.. no error. + +Music_IWLoad16BitSample: + Push EBX + + ShR EBX, 1 + Inc BX + Mov [CS:IWDataTable+DI], EBX + + Mov ES, CS:SongDataArea + Pop EDI ; EDI = location in IW mem + + Sub ECX, 4 + ClI + + Push BP + + Mov EBP, EDX + + Call IWSetPosition + + Mov AX, [DS:ESI+EBP*2] + Call LoadIWSample + Mov AL, AH + Call LoadIWSample + + Call Load16IWSamples + + Pop BP + + Xor BX, BX + + Mov AL, [FS:BP+12h] + Test AL, 16 + JZ Music_IWLoad16BitSample11B + + Mov ESI, [FS:BP+34h] + + Test AL, 64 + JZ Music_IWLoad16BitSample11 + + Mov ESI, [FS:BP+38h] + Sub ESI, 2 + JNC Music_IWLoad16BitSample11 + + Xor ESI, ESI + +Music_IWLoad16BitSample11: + Mov EAX, Not 0 + Mov CL, CS:Compress + ShL EAX, CL + And ESI, EAX + + Add ESI, ESI + Int 3 + + Mov BX, [SI] + +Music_IWLoad16BitSample11B: + Mov AX, BX + Call LoadIWSample + Mov AL, AH + Call LoadIWSample + + StI + Jmp Music_IWLoadSample3 ; Return.. no error. + + +EndP LoadSample + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release, 0 based +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + LEA DI, [EAX*4+Offset IWDataTable] + ; Now to release the last + ; sample from IW memory if + ; able to. + + Mov EBP, [CS:DI] ; EBP = sample pointer. + Cmp EBP, 0FFFFFFFFh + JE ReleaseSample3 + +ReleaseSample4: + MovZX EAX, CS:IWMemory + SHL EAX, 10 + + ; If (MaxMem-(sample location in bank + sample length + 2)) = memory remaining, + ; then release memory. + + Mov ECX, [SI+30h] + Mov DL, [SI+12h] + Test DL, 16 + JZ ReleaseSample7 + + Cmp ECX, [SI+38h] + JBE ReleaseSample7 + + Mov ECX, [SI+38h] + + Test DL, 32 + JZ ReleaseSample7 + + Cmp ECX, [SI+44h] + JAE ReleaseSample7 + + Mov ECX, [SI+44h] + +ReleaseSample7: + Push EBX + Mov EBX, ECX + Mov CL, CS:Compress + ShR EBX, CL + Mov ECX, EBX + Pop EBX + + Inc ECX + Mov EDI, 1 + + Test DL, 2 + JZ ReleaseSample8Bit + + Cmp CS:Convert16To8Bit, 0 + JNZ ReleaseSample8Bit + + Add ECX, ECX + Inc DI + + ; EBP = pointer for 16 bit + ; need to convert back: + Add EBP, EBP + +ReleaseSample8Bit: + Cmp IWMemorySegmented, 0 + JNE ReleaseSampleSegmented1 + + Sub EAX, EBP + Sub EAX, ECX + + Cmp EAX, IWMemoryFree + JNE ReleaseSample3 + + Add ECX, EDI + Add IWMemoryFree, ECX + + Ret + +ReleaseSampleSegmented1: ; EBP = sample pointer + ; if EBP-EDI = mem remaining in + ; segment, then add ECX+EDI... + Xor AX, AX + Sub EBP, EDI + Add ECX, EDI + Mov EDI, EBP + + And EBP, 3FFFFFh + + ShR EDI, 22 + And DI, 3 + Mov EAX, [IWBank1+EDI*4] + Cmp EAX, EBP + JNE ReleaseSample3 + + Add [IWBank1+EDI*4], ECX + +ReleaseSample3: + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Push EAX + Push CX + Push ES + Push DI + + MovZX EAX, IWMemory ; Number of kbytes + ShL EAX, 10 ; Translate to bytes + + Cmp IWMemorySegmented, 0 + JE ResetMemory1 + + Xor AH, AH + Mov AL, [IWBankTable] + ShL EAX, 16 + Mov IWBank1, EAX + + Xor AH, AH + Mov AL, [IWBankTable+1] + ShL EAX, 16 + Mov IWBank2, EAX + + Xor AH, AH + Mov AL, [IWBankTable+2] + ShL EAX, 16 + Mov IWBank3, EAX + + Xor AH, AH + Mov AL, [IWBankTable+3] + ShL EAX, 16 + Mov IWBank4, EAX + + Jmp ResetMemory2 + +ResetMemory1: + Sub EAX, 64 ; Safety bytes. + Mov IWMemoryFree, EAX + +ResetMemory2: + Push CS + Pop ES + Mov DI, Offset IWDataTable + Mov CX, 200 + Mov AX, 0FFFFh + Rep StosW + + Pop DI + Pop ES + Pop CX + Pop EAX + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + Push CS + Pop DS + Assume DS:Driver + + Mov EAX, IWMemoryFree + Cmp IWMemorySegmented, 0 + JE GetStatus1 + + Mov EAX, IWBank1 + Add EAX, IWBank2 + Add EAX, IWBank3 + Add EAX, IWBank4 + +GetStatus1: + Mov SI, Offset IWFreeMsg + ShR EAX, 10 + + ClC + + Ret + +EndP GetStatus + Assume DS:Nothing + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset IWScreenList + + ClC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far + + Ret + +EndP SetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far + + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetConvert Far + + Mov AX, [SI+22] + Mov CS:Convert16To8Bit, AL + Call Music_LoadAllSamples + + Mov AX, 1 + Ret + +EndP SetConvert + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetConvert Far + + Push CS + Pop ES + Mov DI, Offset Convert16To8Bit + Ret + +EndP GetConvert + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetCompress Far + + Mov AX, [SI+22] + Mov CS:Compress, AL + Call Music_LoadAllSamples + + Mov AX, 1 + Ret + +EndP SetCompress + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetCompress Far + + Push CS + Pop ES + Mov DI, Offset Compress + + Ret + +EndP GetCompress + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Constants Table ************* + +MaxNumberOfChannels DW 32 ; Maximum number of channels the + ; driver can handle. +StopAfterPlay DW 0 +DefaultChannels DW 32 + +DriverFlags DW 1 ; MIDI Out suported + DW 4 Dup (0) + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + DW Offset DetectIW + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + + DW Offset SendUARTOut ; MIDI output! + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End + + *********************** Notes ******************* + + UltraSound Output Structure + + 0 1 2 3 4 5 6 7 8 9 + ÚÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÂ +0000:³(Flags)³LastVol ³ + ÃÄÄÄÂÄÄÄÅÄÄÄÂÄÄÄÅÄÄÄÂÄÄÄÂÄÄÄÂÄÄÄÅÄÄÄÂÄÄÄÅ + + diff --git a/SoundDrivers/K6MSAM.INC b/SoundDrivers/K6MSAM.INC new file mode 100755 index 0000000..445a223 --- /dev/null +++ b/SoundDrivers/K6MSAM.INC @@ -0,0 +1,388 @@ +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Align 4 +include q.inc +FilterParameters DB 64 Dup (07Fh), 64 Dup (0) +Const2048 DD 16384.0 +FreqMultiplier DD 3A9F7867h ; = 1/(2*PI*110.0*2^0.25) +FreqParameterMultiplier DD 0B92AAAAAh ; = -1/(24*256) + +NUMBEROFFILTERBANDS = 4 + +IF OUTPUTFILTERENABLED +LastFilter DD NUMBEROFFILTERBANDS*2 Dup (0) ; 4 stereo values +FilterCoefficients DD NUMBEROFFILTERBANDS*2 Dup (0) +FilterVolumes DD NUMBEROFFILTERBANDS Dup (0) +ENDIF + +FilterFreqValue DW 0 +NewControlWord DW 7Fh + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc MixSamples ; Given DS:SI = info tables, CX = numchannels + Assume DS:Nothing + + ; 1. Clean buffer + ; + update variables + ; 2. Update parameters + ; 3. Mix func + ; 4. Return + + Push CX + + Mov CX, BytesToMix + Mov ES, CS:MixSegment + Mov DI, DMABUFFERLENGTH*2+80 + Xor EAX, EAX + Mov DX, CX + Add CX, CX + + Mov CS:MixTransferOffset, DI + + Cmp CS:Stereo, 0 + JE CS:MixSamples1 + + Mov DX, CX + +MixSamples1: + Rep StosD + Mov CS:MixTransferRemaining, DX + + Pop CX + +MixSamples2: + Test Byte Ptr [SI], 1 + JZ MixSamplesEnd2 + + Cmp Byte Ptr [SI+36h], 100 + JE MixSamplesEnd2 + + Push CX + Mov CX, [SI] + + Test CH, 2 + JZ MixSamplesNoStop + + And Byte Ptr [SI], Not 1 + + Cmp MixMode, 2 + JB MixSamplesEnd + + Mov DWord Ptr [SI+0Ch], 0 + Jmp MixModeCommon + +MixSamplesNoStop: + Test CL, 20h ; New freq? + JZ MixSamples5 + + Mov AX, [SI+10h] + Mov DX, [SI+12h] + Mov BX, MixSpeed + Cmp DX, BX + JAE MixSamplesHandleError + + Div BX + ShL EAX, 16 + Xor AX, AX + Div BX + Mov STEPVALUE, EAX + +MixSamples4: + Test CH, 1 + JZ MixSamples5 + + Xor EAX, EAX + Mov [SI+3Ch], AX ; For filter. + Mov [SI+6Eh], AX + + Mov DWord Ptr [SI+1Ch], EAX ; Current Volume = 0 + ; for volume sliding. + Mov [SI+06h], DX + Mov [SI+5Eh], AX + Mov [SI+7Eh], AX + +MixSamples5: + Test CX, 8540h ; New volume or panning? + JZ MixSamplesMix + + Mov AX, 4*60 + + Test CH, 8 ; Muted? + JZ MixMMXNoMute + + Xor EDX, EDX + Mov [SI+06h], DX + Mov [SI+0Ch], EDX + Mov [SI+5Eh], DX + Mov [SI+1Ch], EDX + Mov [SI+6Eh], DX + Mov [SI+3Ch], DX + Mov [SI+7Eh], DX + + Xor BX, BX + Mov BL, [SI+3Ah] + + Test BL, BL + JS MixModeCommon1 + + Mov DL, [CS:FilterParameters+BX] + Mov BL, [CS:FilterParameters+BX+64] + + Mov [SI+5Bh], DL + Mov [SI+3Fh], BL + + Jmp MixModeCommon1 + +MixMMXNoMute: + Xor BX, BX + Mov BL, [SI+3Ah] + + Test BL, BL ; Disowned? Then use channel filters. + JNS MixGetChannelFilters + + Mov BL, [SI+3Fh] + Jmp MixChannelFilters + +MixGetChannelFilters: + ; Filter = [FilterParameters+BX] + ; Q = [FilterParameters+BX+64] + + Mov AL, [CS:FilterParameters+BX] ; AX = Filter + Mov BL, [CS:FilterParameters+BX+64] ; BX = Q + +; If the values are different, then force recalculate volume. (and hence mixmode) + + Cmp [SI+5Bh], AL + JE MixChannelFiltersSame + Cmp [SI+3Fh], BL + JE MixChannelFiltersSame + + Mov DWord Ptr [SI+0Ch], 0 + +MixChannelFiltersSame: + Mov [SI+5Bh], AL + Mov [SI+3Fh], BL + +MixChannelFilters: + Cmp MixMode, 3 + JNE MixMMXNoFilters + + Mov AL, [SI+3Eh] + Mul Byte Ptr [SI+5Bh] + + Mov CS:FilterFreqValue, AX + + Cmp AX, 127*255 + JNE MixChannelFiltersOK + Test BL, BL + JZ MixMMXNoFilters + +MixChannelFiltersOK: + ShL BX, 2 + + FNInit + FLdCW [CS:NewControlWord] + + FILD [CS:FilterFreqValue] ; 0->127*256 + FMul [CS:FreqParameterMultiplier] ; -i/(24*256) + FLd ST + FRndInt + FSub ST(1), ST + FXCh + F2XM1 + FLd1 + FAdd + FScale ; = 2^(i/24*256) + FMul [CS:FreqMultiplier] ; = r + FLd ST ; r, r + FMul ST(1), ST ; r, r^2 + + FLd [CS:QualityFactorTable+BX] ; 2d, r, r^2 + FMul ST(1), ST ; 2d, 2dr, r^2 + FAdd + + FLd1 ; 1, d+1, e + FXCh ; d+1, 1, e + FSubR ST(1), ST + FAdd ST, ST(2) ; 1+d+e, d, e + FDivR Const2048 ; 1/(1+d+e), d, e + FISt Word Ptr [SI+5Eh] ; + FLd ST(2) ; e, 1/(1+d+e), d, e + FAdd ST, ST + FAddP ST(2), ST ; 1/(1+d+e), d+2e, e + FMul ST(2), ST ; 1/(1+d+e), d+2e, e/(1+d+e) + FMul + FIStP Word Ptr [SI+6Eh] + FChs + FIStP Word Ptr [SI+7Eh] + FStP ST + Mov DWord Ptr [SI+0Ch], 0 + +MixMMXNoFilters: + Mov EBX, [SI+0Ch] + + Cmp Stereo, 0 + JNE MixMMXStereo + +MixMMXMono: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 9 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + + Jmp MixModeVolumeCheck + +MixMMXStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE MixMMXSurround + + Mul Byte Ptr MixVolume ; 0->128 + Mul Word Ptr [SI+4Ah] ; 0->32768 + ShRD AX, DX, 15 ; Maxvol = 8192 + Mov [SI+0Eh], AX ; Store into right volume + + Mov AL, 64 ; Do left volume + Sub AL, [SI+37h] ; AL = 64-FinalPan + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 15 + Mov [SI+0Ch], AX + + Jmp MixModeVolumeCheck + +MixMMXSurround: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 10 + Mov [SI+0Ch], AX + Neg AX + Mov [SI+0Eh], AX + +MixModeVolumeCheck: + Test CH, 3+4 + JNZ MixModeCommon + + Cmp EBX, [SI+0Ch] ; Same as last volume? + JE MixSamplesMix + +MixModeCommon: ; Requires AX = 30 etc. depending + ; On mixing mode type. + ; This will add 180 for 16-bit, + ; And sort out loop types. + Mov AX, MixModeOffset + + Cmp DWord Ptr [SI+0Ch], 0 + JNE MixModeActualMix + + Cmp MixMode, 2 + JB MixMMXGeneralNoRamp + + Cmp DWord Ptr [SI+1Ch], 0 + JNE MixModeActualMix + +MixMMXGeneralNoRamp: + Mov AX, 4*60 + Jmp MixModeCommon1 + +MixModeActualMix: + Cmp MixMode, 3 + JNE MixModeFilter + + Cmp Word Ptr [SI+6Eh], 0 + JNE MixModeFilter + Cmp Word Ptr [SI+7Eh], 0 + JNE MixModeFilter + + Sub AX, 60 + +MixModeFilter: + Test Byte Ptr [SI+18h], 2 ; 16 bit? + JZ MixModeCommon1 + + Add AX, 30 + +MixModeCommon1: + Cmp Byte Ptr [SI+0Ah], 8 + JB MixModeCommon3 ; No loop + JE MixModeCommon2 ; Forwards loop + + Add AX, 10 + +MixModeCommon2: + Add AX, 10 + +MixModeCommon3: + Add AX, Offset MixFunctionTables + Mov [SI+8], AX ; Offset... + +MixSamplesMix: + Mov BX, [SI+8] ; BX = offset into + Mov EAX, [CS:BX+2] + Mov DWord Ptr PreMixFunction, EAX + Mov EAX, [CS:BX+6] + Mov DWord Ptr MixFunctionSeparateBackwards, EAX + + Mov AX, BytesToMix + Mov MixBlockSize, AX + Mov MixBufferOffset, DMABUFFERLENGTH*2+80 + + Mov EAX, CURRENTPOSITION + Mov OLDPOSITION, EAX + + Push Word Ptr [SI+8] + Call Word Ptr [CS:BX] + Pop BX + + And Word Ptr [SI], 0111100010001101b + + Cmp BX, Offset MixFunctionTables+60*2 + JB MixSamplesEnd + Cmp BX, Offset MixFunctionTables+60*4 + JAE MixSamplesEnd + + MovDR AX, MM6 + Mov [SI+0Ch], EAX + Mov [SI+1Ch], EAX + + Cmp BX, Offset MixfunctionTables+60*3 + JB MixSamplesEnd + + Mov ES, CS:MixSegment + Mov DX, [ES:10h] + Mov BX, [ES:14h] + Mov [SI+3Ch], DX + Mov [SI+6h], BX + Jmp MixSamplesEnd + +MixSamplesHandleError: + Mov Word Ptr [SI], 200h + + Test Byte Ptr [SI+3Ah], 80h + JNZ MixSamplesEnd + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Turn off channel + +MixSamplesEnd: + Pop CX + +MixSamplesEnd2: + Add SI, 128 + Dec CX + JNZ MixSamples2 + +IF OUTPUTFILTERENABLED + include equalize.inc +ENDIF + Ret + +EndP MixSamples + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + diff --git a/SoundDrivers/K6TRANS.INC b/SoundDrivers/K6TRANS.INC new file mode 100755 index 0000000..3bfb278 --- /dev/null +++ b/SoundDrivers/K6TRANS.INC @@ -0,0 +1,119 @@ + +; To be embedded within the IRQ handler. + + Push DX + + Cmp CS:Stereo, 0 + JNE TransferStereoBufferMMX + +TransferMonoBufferMMX: ; DX = number of 32 bit numbers -> 16 bit. + + Push DX + ShR DX, 3 + JZ TransferMonoBufferMMX2 + +TransferMonoBufferMMX1: + MovD MM0, [SI] + MovD MM1, [SI+8] + MovD MM2, [SI+10h] + MovD MM3, [SI+18h] + MovD MM4, [SI+20h] + MovD MM5, [SI+28h] + MovD MM6, [SI+30h] + MovD MM7, [SI+38h] + + PUnpckLDQ MM0, MM1 ; MM0 = S2|S1 + PUnpckLDQ MM2, MM3 ; MM2 = S4|S3 + PUnpckLDQ MM4, MM5 ; MM4 = S6|S5 + PUnpckLDQ MM6, MM7 ; MM6 = S8|S7 + + PF2ID MM0, MM0 + PF2ID MM2, MM2 + PF2ID MM4, MM4 + PF2ID MM6, MM6 + + + PackSSDW MM0, MM2 + PackSSDW MM4, MM6 + + MovQ [DI], MM0 + MovQ [DI+8], MM4 + + Add SI, 40h + Add DI, 10h + + Dec DX + JNZ TransferMonoBufferMMX1 + +TransferMonoBufferMMX2: + Pop CX + Mov DX, CX + + And CX, 7 + JZ TransferMonoBufferMMX4 + +TransferMonoBufferMMX3: + MovD MM0, [SI] + PF2ID MM0, MM0 + MovD EAX, MM0 + StosW + Add SI, 8 + + Loop TransferMonoBufferMMX3 + +TransferMonoBufferMMX4: + Jmp MMXMixTransferEnd + +TransferStereoBufferMMX: ; DX is always an even number for stereo + Push DX + + ShR DX, 3 + JZ TransferStereoBufferMMX2 + +TransferStereoBufferMMX1: ; DX = number of 32 bit numbers -> 16 bit + MovQ MM0, [SI] + MovQ MM1, [SI+8] + MovQ MM2, [SI+10h] + MovQ MM3, [SI+18h] + + PF2ID MM0, MM0 + PF2ID MM1, MM1 + PF2ID MM2, MM2 + PF2ID MM3, MM3 + + PackSSDW MM0, MM1 + PackSSDW MM2, MM3 + + MovQ [DI], MM0 + MovQ [DI+8], MM2 + + Add SI, 20h + Add DI, 10h + + Dec DX + JNZ TransferStereoBufferMMX1 + +TransferStereoBufferMMX2: + Pop CX + Mov DX, CX + + And CX, 7 + ShR CX, 1 ; Always an even number! + JZ TransferStereoBufferMMX4 + +TransferStereoBufferMMX3: + MovQ MM0, [SI] + PF2ID MM0, MM0 + PackSSDW MM0, MM0 + MovD [DI], MM0 + + Add SI, 8 + Add DI, 4 + + Loop TransferStereoBufferMMX3 + +TransferStereoBufferMMX4: + +MMXMixTransferEnd: + Pop DX + diff --git a/SoundDrivers/LOADSAM.INC b/SoundDrivers/LOADSAM.INC new file mode 100755 index 0000000..6eb0a12 --- /dev/null +++ b/SoundDrivers/LOADSAM.INC @@ -0,0 +1,71 @@ +Proc LoadSample Far ; Fix up end of sample bytes + + PushAD + Push DS + Push ES + Push FS + + Mov FS, CS:SongDataArea + Mov BP, AX + Add BP, BP + Mov BP, [FS:64910+BP] + + Xor CX, CX ; From the start of the sample.. + Call GetSampleLocation ; Returns DS:ESI, ECX = length + JC LoadSampleEnd ; Zero flag ON if 16 bit.. + + Xor EAX, EAX + Mov BL, [FS:BP+12h] + + Test BL, 10h ; Loop + JZ LoadSample2 + + Mov ESI, [FS:BP+34h] ; Start of loop + Test BL, 40h ; Pingpong? + JZ LoadSample1 + + Mov ESI, [FS:BP+38h] + Sub ESI, 2 + JNC LoadSample1 + + Xor ESI, ESI + +LoadSample1: + Test BL, 2 + JZ LoadSample4 + + Add ESI, ESI + +LoadSample4: + Int 3 + Mov AL, [SI] + Inc ESI + Int 3 + Mov AH, [SI] + +LoadSample2: + Mov ESI, [FS:BP+30h] + Test BL, 2 + JZ LoadSample3 + + Add ESI, ESI + +LoadSample3: + Int 3 + Mov [SI], AL + Inc ESI + Int 3 + Mov [SI], AH + +LoadSampleEnd: + Pop FS + Pop ES + Pop DS + PopAD + + StC + Ret + +EndP LoadSample + + diff --git a/SoundDrivers/LPT1DRV.ASM b/SoundDrivers/LPT1DRV.ASM new file mode 100755 index 0000000..c52b0fd --- /dev/null +++ b/SoundDrivers/LPT1DRV.ASM @@ -0,0 +1,904 @@ + + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;********************************** + +STEREOENABLED EQU 0 +DMABUFFERLENGTH EQU 4096 +MIXRESOLUTION EQU 16 ; 16 bit mixing for the SB Pro +MIXTABLESIZE EQU 2*256*65 + +SBProMsg DB "Using DAC on LPT1, Port ", 0FDh, "Xh", 0 + +SBProNoMemoryMsg DB " Using DAC on LPT1", 13 + DB " Error: Insufficient memory", 0 + +ReinitMsg DB "DAC on LPT1 reinitialised", 0 + +DSPVersion DW 0 +Forced DB 0 +InInterrupt DB 0 + +BytesToMix DW 1000 +MixSpeed DW 22000 +MixConst DW 0 + +MixSegment DW 0 +DMASegment DW 0 + +MixTransferOffset DW 0 +MixTransferRemaining DW 0 + +DMASize DW 2048 + +OldIRQHandler DD 0 +TimerAccumulator DW 0 + +; ÄÄ MixingRoutines ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixBufferPos DW 0 +OutputBufferPos DW 0 +OutputBlockEnd DW 1024 + +include mix.inc +include mono12b.mix + +MixFunctionTables Label + +include mono12b.inc ; contains the tables + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixConst ; Work out value.. and nearest + ; mixspeed value. + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, CmdLineMixSpeed + Mov CX, MixSpeed + + Cmp AX, 12000 + JB GetMixConst1 + + Cmp AX, 44100 + JA GetMixConst1 + + Mov CX, AX + +GetMixConst1: + Mov DX, 0012h + Mov AX, 34DDh + + Div CX + ; AX = mix const + Mov MixConst, AX + + Mov DX, 12h + Mov AX, 34DDh + Div MixConst + + Mov MixSpeed, AX + + Pop ES + Pop DS + PopA + Ret + +EndP GetMixConst + Assume DS:Nothing + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far + + Push ES + + Xor AX, AX + Mov ES, AX + Mov AX, [ES:408h] ; LPT1 port + + Pop ES + And AX, AX + JZ DetectCard1 + + Mov Word Ptr CS:LPTPortNumber, AX + + Mov EAX, 'Jeff' + ClC + Ret + +DetectCard1: + StC + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc MixSamples ; Given DS:SI = info tables, CX = numchannels + + ; 1. Clean buffer + ; + update variables + ; 2. Update parameters + ; 3. Mix func + ; 4. Return + + Push CX + + Mov CX, BytesToMix + Mov ES, MixSegment + Mov DI, MIXTABLESIZE + Mov AX, 2020h + + Mov BX, CX ; BX = bytes to mix + Mov DX, CX + + Mov MixTransferOffset, DI ; } Memory write + Rep StosW ; } Memory write + Mov MixTransferRemaining, DX ; } + + Pop CX + +MixSamples2: + Test Byte Ptr [SI], 1 + JZ MixSamplesEnd2 + Cmp Byte Ptr [SI+36h], 100 + JE MixSamplesEnd2 + + Push CX + Mov CX, [SI] + + Test CH, 2 + JZ MixSamples3 + And Byte Ptr [SI], Not 1 + Jmp MixSamplesEnd + +MixSamples3: + Test CL, 20h ; New freq? + JZ MixSamples5 + + Mov AX, [SI+10h] + Mov DX, [SI+12h] + Mov BX, MixSpeed + Cmp DX, BX + JAE MixSamplesHandleError + + Div BX + ShL EAX, 16 + Xor AX, AX + Div BX + Mov STEPVALUE, EAX + +MixSamples4: + Test CH, 1 + JZ MixSamples5 + + Mov DWord Ptr [SI+1Ch], 0 ; Current Volume = 0 + ; for volume sliding. +MixSamples5: + Test CX, 8440h ; New volume or panning? + JZ MixSamplesMix + + Xor AX, AX + Test CH, 8 ; Muted? + JNZ MixModeCommon + +Mix0Mode: ; 16-bit mixing, no interpolation, no ramping +Mix0ModeMono: + Mov AL, [SI+20h] + ShR AL, 1 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AX, 30 ; Use left only-mixing for mono + +MixModeCommon: ; Requires AX = 30/60/90 etc. depending + ; On mixing mode type. + ; This will add 180 for 16-bit, + ; And sort out loop types. + Mov BL, [SI+0Ah] + Test Byte Ptr [SI+18h], 2 ; 16 bit? + JZ MixModeCommon1 + + Add AX, 60 + +MixModeCommon1: + Cmp BL, 8 + JB MixModeCommon3 ; No loop + JE MixModeCommon2 ; Forwards loop + + Add AX, 10 + +MixModeCommon2: + Add AX, 10 + +MixModeCommon3: + Add AX, Offset MixFunctionTables + Mov [SI+8], AX ; Offset... + + +MixSamplesMix: + Mov BX, [SI+8] ; BX = offset into + Mov EAX, [CS:BX+2] + Mov DWord Ptr PreMixFunction, EAX + Mov EAX, [CS:BX+6] + Mov DWord Ptr MixFunctionSeparateBackwards, EAX + + Mov AX, MixTransferRemaining + Mov MixBlockSize, AX + Mov MixBufferOffset, MIXTABLESIZE + + Mov EAX, CURRENTPOSITION + Mov OLDPOSITION, EAX + + Call Word Ptr [CS:BX] + + And Word Ptr [SI], 0111100010001101b + Jmp MixSamplesEnd + +MixSamplesHandleError: + Mov Word Ptr [SI], 200h + + Test Byte Ptr [SI+3Ah], 80h + JNZ MixSamplesEnd + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Turn off channel + +MixSamplesEnd: + Pop CX + +MixSamplesEnd2: + Add SI, 128 + Dec CX + JNZ MixSamples2 + + Ret + +EndP MixSamples + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PCSpeakerIRQHandler + + Push AX + Push BX + Push DX + Push DS + + Mov DS, CS:DMASegment + Mov BX, CS:OutputBufferPos + +LPTPortNumber EQU $+1 + Mov DX, 1234h + + Mov AL, [BX] + Out DX, AL + + Mov AX, CS + Mov DS, AX + Assume DS:Driver + + Inc BX + ; OK.. which IRQ handler? + Mov AX, MixConst + Add TimerAccumulator, AX + JC PCSpeakerIRQHandler1 + + Mov AL, 20h + Out 20h, AL + Jmp PCSpeakerIRQHandler2 + +PCSpeakerIRQHandler1: + PushF + Call OldIRQHandler + +PCSpeakerIRQHandler2: + Mov OutputBufferPos, BX + Cmp BX, OutputBlockEnd + JAE PCSpeakerIRQHandler3 + +PCSpeakerIRQHandlerEnd: + Pop DS + Pop DX + Pop BX + Pop AX + + IRet + +PCSpeakerIRQHandler3: + Mov BX, DMASize + Mov AX, OutputBlockEnd + Add AX, BX + Cmp AX, DMABUFFERLENGTH + JBE PCSpeakerIRQHandler4 + + Mov AX, BX + Mov OutputBufferPos, 0 + +PCSpeakerIRQHandler4: + Mov OutputBlockEnd, AX + + Cmp InInterrupt, 0 + JA PCSpeakerIRQHandlerEnd + + Inc InInterrupt + + ClD + + PushAD + Push ES + + Mov ES, CS:DMASegment + Mov DI, OutputBufferPos + + Call SaveEMSPageFrame + + StI + ; BX = bytes required + + Cmp MixTransferRemaining, 0 + JNE SBProIRQHandler4 + Assume DS:Nothing + +SBProIRQHandler3: + Push BX + Push ES + Push DI + + Call Update + Call MixSamples + + Pop DI + Pop ES + Pop BX + +SBProIRQHandler4: + Mov DS, MixSegment + Mov SI, MixTransferOffset + Mov DX, BX ; DX = samples to transfer + Cmp DX, MixTransferRemaining + JBE SBProIRQHandler5 + + Mov DX, MixTransferRemaining + +SBProIRQHandler5: + Push BX + Push DX + +SBProIRQHandler6: + Mov AX, [SI] + SAR AX, 6 + + Test AH, AH + JNZ SBProIRQHandlerClip1 + +SBProIRQHandler7: + StosB ; } Memory write + + Add SI, 2 + Dec DX + JNZ SBProIRQHandler6 + + Pop DX + Pop BX + + Sub MixTransferRemaining, DX ; } Memory write + Sub BX, DX + JNZ SBProIRQHandler3 + + Mov MixTransferOffset, SI ; } Memory write + + Call RestoreEMSPageFrame + + Dec InInterrupt + +PCSpkEnd2: + Pop ES + PopAD + Pop DS + Pop DX + Pop BX + Pop AX + IRet + +SBProIRQHandlerClip1: + Mov AL, 0 + JS SBProIRQHandler7 + Mov AL, 0FFh + Jmp SBProIRQHandler7 + +EndP PCSpeakerIRQHandler + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + + PushAD + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Mov OutputBufferPos, 0 + Mov OutputBlockEnd, 1024 + + Mov AL, 34h ; Program IRQ 0. LSB&MSB, Rate gen + Out 43h, AL + + Mov AX, MixConst + Out 40h, AL + Mov AL, AH + Out 40h, AL + + Xor AX, AX + Mov ES, AX + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset PCSpeakerIRQHandler + + ClI + + XChg [ES:20h], EAX + Mov OldIRQHandler, EAX + + StI + + Pop ES + Pop DS + PopAD + + Ret + +EndP SetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIRQ + + PushAD + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Mov AL, 34h ; Reset IRQ calling rate. + Out 43h, AL + Xor AL, AL + Out 40h, AL + Out 40h, AL + + Xor AX, AX + Mov ES, AX + + Mov EAX, OldIRQHandler + Mov [ES:20h], EAX + + Pop ES + Pop DS + PopAD + + Ret + +EndP ResetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Call GetEMSPageFrame + Mov EMSPageFrame, AX + + Call GetMixConst + + Mov AX, 661 + Mul MixSpeed + Add AX, 0FFFFh + AdC DX, 2080 + + Mov BX, DMABUFFERLENGTH/16 + Add BX, DX + + ; Allocate MixSegment first + Mov AH, 48h + + Int 21h + JNC InitSound1 + +InitSoundNoMemory: + Mov SI, Offset SBProNoMemoryMsg + Ret + +InitSound1: + Mov MixSegment, AX + Add AX, DX + Mov DMASegment, AX + + Call GetTempo + Call SetTempo + Call SetIRQ + + Mov SI, Offset SBProMsg + Mov AX, Word Ptr LPTPortNumber + + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Call ResetIRQ + Call SetIRQ + + Mov SI, Offset ReInitMsg + Mov BX, 40 + Call SetInfoLine + + Pop ES + Pop DS + PopA + + Ret + +EndP ReInitSound + Assume DS:Nothing + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Mov AX, MixSegment + Test AX, AX + JZ UnInitSound1 + + Mov ES, AX + Mov AH, 49h ; Release MixSegment + Int 21h + + Call ResetIRQ + +UnInitSound1: + Ret + +EndP UnInitSound + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + Ret + +EndP Poll + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Push AX + Push BX + Push DX + + Push BX + + Mov AX, MixSpeed + Mov BX, AX + Xor DX, DX + + ShL AX, 1 + RCL DX, 1 ; DX:AX = Mixspeed*2 + + ShR BX, 1 ; BX = Mixspeed/2 + + Add AX, BX + AdC DX, 0 ; DX:AX = Mixspeed*2.5 + + Pop BX ; BX = tempo + Div BX + + Mov BytesToMix, AX + + Pop DX + Pop BX + Pop AX + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + PushA + Push DS + + Mov BX, AX ; BX = MixVolume + + Mov AX, CS:MixSegment + Test AX, AX + JZ SetMixVolume2 + + Mov DS, AX + + Mov CX, MIXTABLESIZE/2 + Mov SI, MIXTABLESIZE-2; Starting point - working backwards + +SetMixVolume1: + Mov AX, CX + + Dec AX ; AH = volume, AL = wave value. + Xor DX, DX + XChg AH, DL ; DL = Volume, AX = wave value + CBW + + IMul DX ; DX:AX = Volume * Wave Value + ; Ranges -8192->8128 + + IMul BX ; DX:AX = Volume * Wave Value * Mixing Volume + ; Ranges -1048576->1040384 + + Add AX, 64 + AdC DX, 0 + + ShRD AX, DX, 7 + Mov [SI], AX + Sub SI, 2 + + Loop SetMixVolume1 + +SetMixVolume2: + Pop DS + PopA + + Ret + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc LoadSample Far + + StC + Ret + +EndP LoadSample + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + StC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far ; Returns AX, given DI + + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far ; Given AX, DI + + Ret + +EndP SetVariable + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. + +StopAfterPlay DW 0 +DefaultChannels DW 64 + DW 5 Dup (0) + + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/LPT2DRV.ASM b/SoundDrivers/LPT2DRV.ASM new file mode 100755 index 0000000..d30e254 --- /dev/null +++ b/SoundDrivers/LPT2DRV.ASM @@ -0,0 +1,904 @@ + + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;********************************** + +STEREOENABLED EQU 0 +DMABUFFERLENGTH EQU 4096 +MIXRESOLUTION EQU 16 ; 16 bit mixing for the SB Pro +MIXTABLESIZE EQU 2*256*65 + +SBProMsg DB "Using DAC on LPT2, Port ", 0FDh, "Xh", 0 + +SBProNoMemoryMsg DB " Using DAC on LPT2", 13 + DB " Error: Insufficient memory", 0 + +ReinitMsg DB "DAC on LPT2 reinitialised", 0 + +DSPVersion DW 0 +Forced DB 0 +InInterrupt DB 0 + +BytesToMix DW 1000 +MixSpeed DW 22000 +MixConst DW 0 + +MixSegment DW 0 +DMASegment DW 0 + +MixTransferOffset DW 0 +MixTransferRemaining DW 0 + +DMASize DW 2048 + +OldIRQHandler DD 0 +TimerAccumulator DW 0 + +; ÄÄ MixingRoutines ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixBufferPos DW 0 +OutputBufferPos DW 0 +OutputBlockEnd DW 1024 + +include mix.inc +include mono12b.mix + +MixFunctionTables Label + +include mono12b.inc ; contains the tables + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixConst ; Work out value.. and nearest + ; mixspeed value. + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, CmdLineMixSpeed + Mov CX, MixSpeed + + Cmp AX, 12000 + JB GetMixConst1 + + Cmp AX, 44100 + JA GetMixConst1 + + Mov CX, AX + +GetMixConst1: + Mov DX, 0012h + Mov AX, 34DDh + + Div CX + ; AX = mix const + Mov MixConst, AX + + Mov DX, 12h + Mov AX, 34DDh + Div MixConst + + Mov MixSpeed, AX + + Pop ES + Pop DS + PopA + Ret + +EndP GetMixConst + Assume DS:Nothing + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far + + Push ES + + Xor AX, AX + Mov ES, AX + Mov AX, [ES:40Ah] ; LPT2 port + + Pop ES + And AX, AX + JZ DetectCard1 + + Mov Word Ptr CS:LPTPortNumber, AX + + Mov EAX, 'Jeff' + ClC + Ret + +DetectCard1: + StC + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc MixSamples ; Given DS:SI = info tables, CX = numchannels + + ; 1. Clean buffer + ; + update variables + ; 2. Update parameters + ; 3. Mix func + ; 4. Return + + Push CX + + Mov CX, BytesToMix + Mov ES, MixSegment + Mov DI, MIXTABLESIZE + Mov AX, 2020h + + Mov BX, CX ; BX = bytes to mix + Mov DX, CX + + Mov MixTransferOffset, DI ; } Memory write + Rep StosW ; } Memory write + Mov MixTransferRemaining, DX ; } + + Pop CX + +MixSamples2: + Test Byte Ptr [SI], 1 + JZ MixSamplesEnd2 + Cmp Byte Ptr [SI+36h], 100 + JE MixSamplesEnd2 + + Push CX + Mov CX, [SI] + + Test CH, 2 + JZ MixSamples3 + And Byte Ptr [SI], Not 1 + Jmp MixSamplesEnd + +MixSamples3: + Test CL, 20h ; New freq? + JZ MixSamples5 + + Mov AX, [SI+10h] + Mov DX, [SI+12h] + Mov BX, MixSpeed + Cmp DX, BX + JAE MixSamplesHandleError + + Div BX + ShL EAX, 16 + Xor AX, AX + Div BX + Mov STEPVALUE, EAX + +MixSamples4: + Test CH, 1 + JZ MixSamples5 + + Mov DWord Ptr [SI+1Ch], 0 ; Current Volume = 0 + ; for volume sliding. +MixSamples5: + Test CX, 8440h ; New volume or panning? + JZ MixSamplesMix + + Xor AX, AX + Test CH, 8 ; Muted? + JNZ MixModeCommon + +Mix0Mode: ; 16-bit mixing, no interpolation, no ramping +Mix0ModeMono: + Mov AL, [SI+20h] + ShR AL, 1 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AX, 30 ; Use left only-mixing for mono + +MixModeCommon: ; Requires AX = 30/60/90 etc. depending + ; On mixing mode type. + ; This will add 180 for 16-bit, + ; And sort out loop types. + Mov BL, [SI+0Ah] + Test Byte Ptr [SI+18h], 2 ; 16 bit? + JZ MixModeCommon1 + + Add AX, 60 + +MixModeCommon1: + Cmp BL, 8 + JB MixModeCommon3 ; No loop + JE MixModeCommon2 ; Forwards loop + + Add AX, 10 + +MixModeCommon2: + Add AX, 10 + +MixModeCommon3: + Add AX, Offset MixFunctionTables + Mov [SI+8], AX ; Offset... + + +MixSamplesMix: + Mov BX, [SI+8] ; BX = offset into + Mov EAX, [CS:BX+2] + Mov DWord Ptr PreMixFunction, EAX + Mov EAX, [CS:BX+6] + Mov DWord Ptr MixFunctionSeparateBackwards, EAX + + Mov AX, MixTransferRemaining + Mov MixBlockSize, AX + Mov MixBufferOffset, MIXTABLESIZE + + Mov EAX, CURRENTPOSITION + Mov OLDPOSITION, EAX + + Call Word Ptr [CS:BX] + + And Word Ptr [SI], 0111100010001101b + Jmp MixSamplesEnd + +MixSamplesHandleError: + Mov Word Ptr [SI], 200h + + Test Byte Ptr [SI+3Ah], 80h + JNZ MixSamplesEnd + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Turn off channel + +MixSamplesEnd: + Pop CX + +MixSamplesEnd2: + Add SI, 128 + Dec CX + JNZ MixSamples2 + + Ret + +EndP MixSamples + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PCSpeakerIRQHandler + + Push AX + Push BX + Push DX + Push DS + + Mov DS, CS:DMASegment + Mov BX, CS:OutputBufferPos + +LPTPortNumber EQU $+1 + Mov DX, 1234h + + Mov AL, [BX] + Out DX, AL + + Mov AX, CS + Mov DS, AX + Assume DS:Driver + + Inc BX + ; OK.. which IRQ handler? + Mov AX, MixConst + Add TimerAccumulator, AX + JC PCSpeakerIRQHandler1 + + Mov AL, 20h + Out 20h, AL + Jmp PCSpeakerIRQHandler2 + +PCSpeakerIRQHandler1: + PushF + Call OldIRQHandler + +PCSpeakerIRQHandler2: + Mov OutputBufferPos, BX + Cmp BX, OutputBlockEnd + JAE PCSpeakerIRQHandler3 + +PCSpeakerIRQHandlerEnd: + Pop DS + Pop DX + Pop BX + Pop AX + + IRet + +PCSpeakerIRQHandler3: + Mov BX, DMASize + Mov AX, OutputBlockEnd + Add AX, BX + Cmp AX, DMABUFFERLENGTH + JBE PCSpeakerIRQHandler4 + + Mov AX, BX + Mov OutputBufferPos, 0 + +PCSpeakerIRQHandler4: + Mov OutputBlockEnd, AX + + Cmp InInterrupt, 0 + JA PCSpeakerIRQHandlerEnd + + Inc InInterrupt + + ClD + + PushAD + Push ES + + Mov ES, CS:DMASegment + Mov DI, OutputBufferPos + + Call SaveEMSPageFrame + + StI + ; BX = bytes required + + Cmp MixTransferRemaining, 0 + JNE SBProIRQHandler4 + Assume DS:Nothing + +SBProIRQHandler3: + Push BX + Push ES + Push DI + + Call Update + Call MixSamples + + Pop DI + Pop ES + Pop BX + +SBProIRQHandler4: + Mov DS, MixSegment + Mov SI, MixTransferOffset + Mov DX, BX ; DX = samples to transfer + Cmp DX, MixTransferRemaining + JBE SBProIRQHandler5 + + Mov DX, MixTransferRemaining + +SBProIRQHandler5: + Push BX + Push DX + +SBProIRQHandler6: + Mov AX, [SI] + SAR AX, 6 + + Test AH, AH + JNZ SBProIRQHandlerClip1 + +SBProIRQHandler7: + StosB ; } Memory write + + Add SI, 2 + Dec DX + JNZ SBProIRQHandler6 + + Pop DX + Pop BX + + Sub MixTransferRemaining, DX ; } Memory write + Sub BX, DX + JNZ SBProIRQHandler3 + + Mov MixTransferOffset, SI ; } Memory write + + Call RestoreEMSPageFrame + + Dec InInterrupt + +PCSpkEnd2: + Pop ES + PopAD + Pop DS + Pop DX + Pop BX + Pop AX + IRet + +SBProIRQHandlerClip1: + Mov AL, 0 + JS SBProIRQHandler7 + Mov AL, 0FFh + Jmp SBProIRQHandler7 + +EndP PCSpeakerIRQHandler + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + + PushAD + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Mov OutputBufferPos, 0 + Mov OutputBlockEnd, 1024 + + Mov AL, 34h ; Program IRQ 0. LSB&MSB, Rate gen + Out 43h, AL + + Mov AX, MixConst + Out 40h, AL + Mov AL, AH + Out 40h, AL + + Xor AX, AX + Mov ES, AX + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset PCSpeakerIRQHandler + + ClI + + XChg [ES:20h], EAX + Mov OldIRQHandler, EAX + + StI + + Pop ES + Pop DS + PopAD + + Ret + +EndP SetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIRQ + + PushAD + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Mov AL, 34h ; Reset IRQ calling rate. + Out 43h, AL + Xor AL, AL + Out 40h, AL + Out 40h, AL + + Xor AX, AX + Mov ES, AX + + Mov EAX, OldIRQHandler + Mov [ES:20h], EAX + + Pop ES + Pop DS + PopAD + + Ret + +EndP ResetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Call GetEMSPageFrame + Mov EMSPageFrame, AX + + Call GetMixConst + + Mov AX, 661 + Mul MixSpeed + Add AX, 0FFFFh + AdC DX, 2080 + + Mov BX, DMABUFFERLENGTH/16 + Add BX, DX + + ; Allocate MixSegment first + Mov AH, 48h + + Int 21h + JNC InitSound1 + +InitSoundNoMemory: + Mov SI, Offset SBProNoMemoryMsg + Ret + +InitSound1: + Mov MixSegment, AX + Add AX, DX + Mov DMASegment, AX + + Call GetTempo + Call SetTempo + Call SetIRQ + + Mov SI, Offset SBProMsg + Mov AX, Word Ptr LPTPortNumber + + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Call ResetIRQ + Call SetIRQ + + Mov SI, Offset ReInitMsg + Mov BX, 40 + Call SetInfoLine + + Pop ES + Pop DS + PopA + + Ret + +EndP ReInitSound + Assume DS:Nothing + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Mov AX, MixSegment + Test AX, AX + JZ UnInitSound1 + + Mov ES, AX + Mov AH, 49h ; Release MixSegment + Int 21h + + Call ResetIRQ + +UnInitSound1: + Ret + +EndP UnInitSound + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + Ret + +EndP Poll + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Push AX + Push BX + Push DX + + Push BX + + Mov AX, MixSpeed + Mov BX, AX + Xor DX, DX + + ShL AX, 1 + RCL DX, 1 ; DX:AX = Mixspeed*2 + + ShR BX, 1 ; BX = Mixspeed/2 + + Add AX, BX + AdC DX, 0 ; DX:AX = Mixspeed*2.5 + + Pop BX ; BX = tempo + Div BX + + Mov BytesToMix, AX + + Pop DX + Pop BX + Pop AX + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + PushA + Push DS + + Mov BX, AX ; BX = MixVolume + + Mov AX, CS:MixSegment + Test AX, AX + JZ SetMixVolume2 + + Mov DS, AX + + Mov CX, MIXTABLESIZE/2 + Mov SI, MIXTABLESIZE-2; Starting point - working backwards + +SetMixVolume1: + Mov AX, CX + + Dec AX ; AH = volume, AL = wave value. + Xor DX, DX + XChg AH, DL ; DL = Volume, AX = wave value + CBW + + IMul DX ; DX:AX = Volume * Wave Value + ; Ranges -8192->8128 + + IMul BX ; DX:AX = Volume * Wave Value * Mixing Volume + ; Ranges -1048576->1040384 + + Add AX, 64 + AdC DX, 0 + + ShRD AX, DX, 7 + Mov [SI], AX + Sub SI, 2 + + Loop SetMixVolume1 + +SetMixVolume2: + Pop DS + PopA + + Ret + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc LoadSample Far + + StC + Ret + +EndP LoadSample + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + StC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far ; Returns AX, given DI + + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far ; Given AX, DI + + Ret + +EndP SetVariable + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. + +StopAfterPlay DW 0 +DefaultChannels DW 64 + DW 5 Dup (0) + + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/M12BIT.INC b/SoundDrivers/M12BIT.INC new file mode 100755 index 0000000..cc25545 --- /dev/null +++ b/SoundDrivers/M12BIT.INC @@ -0,0 +1,49 @@ + + DW Offset UpdateNoLoop, 0, 0, 0, 0 ; Update only + DW Offset UpdateForwardsLoop, 0, 0, 0, 0 + DW Offset UpdatePingPongLoop, 0, 0, 0, 0 + ; Left only + DW Offset MixNoLoop, PreMix12Left8Bit, MFS8Bit, MBS8Bit, Mix12Single8Bit + DW Offset MixForwardsLoop, PreMix12Left8Bit, MFS8Bit, MBS8Bit, Mix12Single8Bit + DW Offset MixPingPongLoop, PreMix12Left8Bit, MFS8Bit, MBS8Bit, Mix12Single8Bit + ; Right only + DW Offset MixNoLoop, PreMix12Right8Bit, MFS8Bit, MBS8Bit, Mix12Single8Bit + DW Offset MixForwardsLoop, PreMix12Right8Bit, MFS8Bit, MBS8Bit, Mix12Single8Bit + DW Offset MixPingPongLoop, PreMix12Right8Bit, MFS8Bit, MBS8Bit, Mix12Single8Bit + ; Central + DW Offset MixNoLoop, PreMix12Central8Bit, MFS8Bit, MBS8Bit, Mix12Central8Bit + DW Offset MixForwardsLoop, PreMix12Central8Bit, MFS8Bit, MBS8Bit, Mix12Central8Bit + DW Offset MixPingPongLoop, PreMix12Central8Bit, MFS8Bit, MBS8Bit, Mix12Central8Bit + ; Stereo + DW Offset MixNoLoop, PreMix12Panned8Bit, MFS8Bit, MBS8Bit, Mix12Panned8Bit + DW Offset MixForwardsLoop, PreMix12Panned8Bit, MFS8Bit, MBS8Bit, Mix12Panned8Bit + DW Offset MixPingPongLoop, PreMix12Panned8Bit, MFS8Bit, MBS8Bit, Mix12Panned8Bit + ; Surround + DW Offset MixNoLoop, PreMix12Surround8Bit, MFS8Bit, MBS8Bit, Mix12Surround8Bit + DW Offset MixForwardsLoop, PreMix12Surround8Bit, MFS8Bit, MBS8Bit, Mix12Surround8Bit + DW Offset MixPingPongLoop, PreMix12Surround8Bit, MFS8Bit, MBS8Bit, Mix12Surround8Bit + + ; 16 bit tables + DW Offset UpdateNoLoop, 0, 0, 0, 0 ; Update only + DW Offset UpdateForwardsLoop, 0, 0, 0, 0 + DW Offset UpdatePingPongLoop, 0, 0, 0, 0 + ; Left only + DW Offset MixNoLoop, PreMix12Left16Bit, MFS16Bit, MBS16Bit, Mix12Single16Bit + DW Offset MixForwardsLoop, PreMix12Left16Bit, MFS16Bit, MBS16Bit, Mix12Single16Bit + DW Offset MixPingPongLoop, PreMix12Left16Bit, MFS16Bit, MBS16Bit, Mix12Single16Bit + ; Right only + DW Offset MixNoLoop, PreMix12Right16Bit, MFS16Bit, MBS16Bit, Mix12Single16Bit + DW Offset MixForwardsLoop, PreMix12Right16Bit, MFS16Bit, MBS16Bit, Mix12Single16Bit + DW Offset MixPingPongLoop, PreMix12Right16Bit, MFS16Bit, MBS16Bit, Mix12Single16Bit + ; Central + DW Offset MixNoLoop, PreMix12Central16Bit, MFS16Bit, MBS16Bit, Mix12Central16Bit + DW Offset MixForwardsLoop, PreMix12Central16Bit, MFS16Bit, MBS16Bit, Mix12Central16Bit + DW Offset MixPingPongLoop, PreMix12Central16Bit, MFS16Bit, MBS16Bit, Mix12Central16Bit + ; Stereo + DW Offset MixNoLoop, PreMix12Panned16Bit, MFS16Bit, MBS16Bit, Mix12Panned16Bit + DW Offset MixForwardsLoop, PreMix12Panned16Bit, MFS16Bit, MBS16Bit, Mix12Panned16Bit + DW Offset MixPingPongLoop, PreMix12Panned16Bit, MFS16Bit, MBS16Bit, Mix12Panned16Bit + ; Surround + DW Offset MixNoLoop, PreMix12Surround16Bit, MFS16Bit, MBS16Bit, Mix12Surround16Bit + DW Offset MixForwardsLoop, PreMix12Surround16Bit, MFS16Bit, MBS16Bit, Mix12Surround16Bit + DW Offset MixPingPongLoop, PreMix12Surround16Bit, MFS16Bit, MBS16Bit, Mix12Surround16Bit diff --git a/SoundDrivers/M12BIT.MIX b/SoundDrivers/M12BIT.MIX new file mode 100755 index 0000000..6c37825 --- /dev/null +++ b/SoundDrivers/M12BIT.MIX @@ -0,0 +1,813 @@ + + ; Different mixing routines required: + ; Left } shared + ; Right } + ; Central + ; Surround + ; Panned ; Each requires 8 bit and 16 bit + ; Single output - for Mono, pure left/pure right + +M12Mix8Single Macro Index + +M12Mix8Single&Index&: + Mov BL, [ES:DI] ;; 2 + Add ERROR, DELTAERROR ;; 1 + Mov AX, [EBX+EBX] ;; 2 + AdC DI, DELTAOFFSET ;; 1 + Sub [SI+(Index-15)*MixResolution/4+EXTRAOFFSET], AX ;; 3 + +EndM + +M12Mix8Central Macro Index + +M12Mix8Central&Index&: + Mov BL, [ES:DI] ;; 2 + Add ERROR, DELTAERROR ;; 1 + Mov AX, [EBX+EBX] ;; 2 + AdC DI, DELTAOFFSET ;; 1 + Sub [SI+(Index-15)*MixResolution/4+EXTRAOFFSET], AX ;; 3 + Sub [SI+(Index-15)*MixResolution/4+MixResolution/8+EXTRAOFFSET], AX ;; 3 + +EndM + +M12Mix8Surround Macro Index + +M12Mix8Surround&Index&: + Mov BL, [ES:DI] ;; 2 + Add ERROR, DELTAERROR ;; 1 + Mov AX, [EBX+EBX] ;; 2 + AdC DI, DELTAOFFSET ;; 1 + Sub [SI+(Index-15)*MixResolution/4+EXTRAOFFSET], AX ;; 3 + Add [SI+(Index-15)*MixResolution/4+MixResolution/8+EXTRAOFFSET], AX ;; 3 + +EndM + + ; Panned output +M12Mix8PannedNext Macro Index + +M12Mix8PannedVolume&Index& EQU $+1 + Mov BH, 12h + Mov BL, [ES:DI] + +EndM + +M12Mix8Panned Macro Index + +M12Mix8Panned&Index&: + Add BX, BX + Add ERROR, DELTAERROR + AdC DI, DELTAOFFSET + Mov AX, [BX] + Sub [SI+(Index-15)*MixResolution/4+EXTRAOFFSET], AX + +M12Mix8PannedRightVolumeOffset&Index& EQU $+3 + Mov AX, [BX+1200h] + + M12Mix8PannedNext %(Index+1) + + Sub [SI+(Index-15)*MixResolution/4+MixResolution/8+EXTRAOFFSET], AX + +EndM + +M12Mix16Single Macro Index + +M12Mix16Single&Index&: + Mov BL, [ES:EDI+EDI+1] + Add ERROR, DELTAERROR + Mov AX, [EBX+EBX] + AdC DI, DELTAOFFSET + Sub [SI+(Index-15)*MixResolution/4+EXTRAOFFSET], AX + +EndM + +M12Mix16Central Macro Index + +M12Mix16Central&Index&: + Mov BL, [ES:EDI+EDI+1] + Add ERROR, DELTAERROR + Mov AX, [EBX+EBX] + AdC DI, DELTAOFFSET + Sub [SI+(Index-15)*MixResolution/4+EXTRAOFFSET], AX + Sub [SI+(Index-15)*MixResolution/4+MixResolution/8+EXTRAOFFSET], AX + +EndM + +M12Mix16Surround Macro Index + +M12Mix16Surround&Index&: + Mov BL, [ES:EDI+EDI+1] + Add ERROR, DELTAERROR + Mov AX, [EBX+EBX] + AdC DI, DELTAOFFSET + Sub [SI+(Index-15)*MixResolution/4+EXTRAOFFSET], AX + Add [SI+(Index-15)*MixResolution/4+MixResolution/8+EXTRAOFFSET], AX + +EndM + + ; Panned output +M12Mix16PannedNext Macro Index + +M12Mix16PannedVolume&Index& EQU $+1 + Mov BH, 12h + Mov BL, [ES:EDI+EDI+1] + +EndM + +M12Mix16Panned Macro Index + +M12Mix16Panned&Index&: + Add BX, BX + Add ERROR, DELTAERROR + AdC DI, DELTAOFFSET + Mov AX, [BX] + Sub [SI+(Index-15)*MixResolution/4+EXTRAOFFSET], AX + +M12Mix16PannedRightVolumeOffset&Index& EQU $+3 + Mov AX, [BX+1200h] + + M12Mix16PannedNext %(Index+1) + + Sub [SI+(Index-15)*MixResolution/4+MixResolution/8+EXTRAOFFSET], AX + +EndM + +;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ + +Mix12Single8BitOffsetTable Label Word + + IndexCounter = 15 + + M12Mix8SingleOffset Macro Index + DW Offset M12Mix8Single&Index& + EndM + + REPT 16 + M12Mix8SingleOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix12Single8Bit + ; AX = count... + + ; Number of times to loop = (Count-1) / 16 + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Push [CS:Mix12Single8BitOffsetTable+BX] + +M12Single8BitVolume EQU $+3 + Mov EBX, 0 ; Set BH = volume + + RetN + + M12Mix8Single 0 + M12Mix8Single 1 + M12Mix8Single 2 + M12Mix8Single 3 + M12Mix8Single 4 + M12Mix8Single 5 + M12Mix8Single 6 + M12Mix8Single 7 + M12Mix8Single 8 + M12Mix8Single 9 + M12Mix8Single 10 + M12Mix8Single 11 + M12Mix8Single 12 + M12Mix8Single 13 + M12Mix8Single 14 + M12Mix8Single 15 + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ M12Mix8Single0 + + Ret + +EndP Mix12Single8Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix12Left8Bit + + Mov AL, [SI+0Eh] + Mov Byte Ptr [CS:M12Single8BitVolume], AL + Ret + +EndP PreMix12Left8Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix12Right8Bit + + Add MixBufferOffset, MixResolution/8 + Mov AL, [SI+0Ch] + Mov Byte Ptr [CS:M12Single8BitVolume], AL + + Ret + +EndP PreMix12Right8Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Mix12Central8BitOffsetTable Label Word + + IndexCounter = 15 + + M12Mix8CentralOffset Macro Index + DW Offset M12Mix8Central&Index& + EndM + + REPT 16 + M12Mix8CentralOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix12Central8Bit + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Push [CS:Mix12Central8BitOffsetTable+BX] + +M12Central8BitVolume EQU $+3 + Mov EBX, 0 ; Set BH = volume + + RetN + + M12Mix8Central 0 + M12Mix8Central 1 + M12Mix8Central 2 + M12Mix8Central 3 + M12Mix8Central 4 + M12Mix8Central 5 + M12Mix8Central 6 + M12Mix8Central 7 + M12Mix8Central 8 + M12Mix8Central 9 + M12Mix8Central 10 + M12Mix8Central 11 + M12Mix8Central 12 + M12Mix8Central 13 + M12Mix8Central 14 + M12Mix8Central 15 + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ M12Mix8Central0 + + Ret + +EndP Mix12Central8Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix12Central8Bit + + Mov AL, [SI+0Eh] + Mov Byte Ptr [CS:M12Central8BitVolume], AL + + Ret + +EndP PreMix12Central8Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Mix12Surround8BitOffsetTable Label Word + + IndexCounter = 15 + + M12Mix8SurroundOffset Macro Index + DW Offset M12Mix8Surround&Index& + EndM + + REPT 16 + M12Mix8SurroundOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix12Surround8Bit + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Push [CS:Mix12Surround8BitOffsetTable+BX] + +M12Surround8BitVolume EQU $+3 + Mov EBX, 0 ; Set BH = volume + + + RetN + + M12Mix8Surround 0 + M12Mix8Surround 1 + M12Mix8Surround 2 + M12Mix8Surround 3 + M12Mix8Surround 4 + M12Mix8Surround 5 + M12Mix8Surround 6 + M12Mix8Surround 7 + M12Mix8Surround 8 + M12Mix8Surround 9 + M12Mix8Surround 10 + M12Mix8Surround 11 + M12Mix8Surround 12 + M12Mix8Surround 13 + M12Mix8Surround 14 + M12Mix8Surround 15 + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ M12Mix8Surround0 + + Ret + +EndP Mix12Surround8Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix12Surround8Bit + + Mov AL, [SI+0Eh] + Mov Byte Ptr [CS:M12Surround8BitVolume], AL + + Ret + +EndP PreMix12Surround8Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Mix12Panned8BitOffsetTable Label Word + + IndexCounter = 15 + + M12Mix8PannedOffset Macro Index + DW Offset M12Mix8Panned&Index& + EndM + + REPT 16 + M12Mix8PannedOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix12Panned8Bit + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Push [CS:Mix12Panned8BitOffsetTable+BX] + + M12Mix8PannedNext 0 + + RetN + + M12Mix8Panned 0 + M12Mix8Panned 1 + M12Mix8Panned 2 + M12Mix8Panned 3 + M12Mix8Panned 4 + M12Mix8Panned 5 + M12Mix8Panned 6 + M12Mix8Panned 7 + M12Mix8Panned 8 + M12Mix8Panned 9 + M12Mix8Panned 10 + M12Mix8Panned 11 + M12Mix8Panned 12 + M12Mix8Panned 13 + M12Mix8Panned 14 + M12Mix8Panned 15 + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ M12Mix8Panned0 + + Ret + +EndP Mix12Panned8Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix12Panned8Bit + + Mov AL, [SI+0Eh] + + IndexCounter = 0 + + PreMix12PannedMacro Macro Index + Mov Byte Ptr [CS:M12Mix8PannedVolume&Index&], AL + EndM + + REPT 17 + PreMix12PannedMacro %IndexCounter + IndexCounter = IndexCounter+1 + EndM + + Mov AL, [SI+0Ch] + Sub AL, [SI+0Eh] + Add AL, AL + + IndexCounter = 0 + + PreMix12PannedMacro2 Macro Index + Mov Byte Ptr [CS:M12Mix8PannedRightVolumeOffset&Index&], AL + EndM + + REPT 16 + PreMix12PannedMacro2 %IndexCounter + IndexCounter = IndexCounter+1 + EndM + + Ret + +EndP PreMix12Panned8Bit + +;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ + +Mix12Single16BitOffsetTable Label Word + + IndexCounter = 15 + + M12Mix16SingleOffset Macro Index + DW Offset M12Mix16Single&Index& + EndM + + REPT 16 + M12Mix16SingleOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix12Single16Bit + ; AX = count... + + ; Number of times to loop = (Count-1) / 16 + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Push [CS:Mix12Single16BitOffsetTable+BX] + +M12Single16BitVolume EQU $+3 + Mov EBX, 0 ; Set BH = volume + + RetN + + M12Mix16Single 0 + M12Mix16Single 1 + M12Mix16Single 2 + M12Mix16Single 3 + M12Mix16Single 4 + M12Mix16Single 5 + M12Mix16Single 6 + M12Mix16Single 7 + M12Mix16Single 8 + M12Mix16Single 9 + M12Mix16Single 10 + M12Mix16Single 11 + M12Mix16Single 12 + M12Mix16Single 13 + M12Mix16Single 14 + M12Mix16Single 15 + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ M12Mix16Single0 + + Ret + +EndP Mix12Single16Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix12Left16Bit + + Mov AL, [SI+0Eh] + Mov Byte Ptr [CS:M12Single16BitVolume], AL + Ret + +EndP PreMix12Left16Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix12Right16Bit + + Add MixBufferOffset, MixResolution/8 + Mov AL, [SI+0Ch] + Mov Byte Ptr [CS:M12Single16BitVolume], AL + + Ret + +EndP PreMix12Right16Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Mix12Central16BitOffsetTable Label Word + + IndexCounter = 15 + + M12Mix16CentralOffset Macro Index + DW Offset M12Mix16Central&Index& + EndM + + REPT 16 + M12Mix16CentralOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix12Central16Bit + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Push [CS:Mix12Central16BitOffsetTable+BX] + +M12Central16BitVolume EQU $+3 + Mov EBX, 0 ; Set BH = volume + + + RetN + + M12Mix16Central 0 + M12Mix16Central 1 + M12Mix16Central 2 + M12Mix16Central 3 + M12Mix16Central 4 + M12Mix16Central 5 + M12Mix16Central 6 + M12Mix16Central 7 + M12Mix16Central 8 + M12Mix16Central 9 + M12Mix16Central 10 + M12Mix16Central 11 + M12Mix16Central 12 + M12Mix16Central 13 + M12Mix16Central 14 + M12Mix16Central 15 + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ M12Mix16Central0 + + Ret + +EndP Mix12Central16Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix12Central16Bit + + Mov AL, [SI+0Eh] + Mov Byte Ptr [CS:M12Central16BitVolume], AL + + Ret + +EndP PreMix12Central16Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Mix12Surround16BitOffsetTable Label Word + + IndexCounter = 15 + + M12Mix16SurroundOffset Macro Index + DW Offset M12Mix16Surround&Index& + EndM + + REPT 16 + M12Mix16SurroundOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix12Surround16Bit + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Push [CS:Mix12Surround16BitOffsetTable+BX] + +M12Surround16BitVolume EQU $+3 + Mov EBX, 0 ; Set BH = volume + + + RetN + + M12Mix16Surround 0 + M12Mix16Surround 1 + M12Mix16Surround 2 + M12Mix16Surround 3 + M12Mix16Surround 4 + M12Mix16Surround 5 + M12Mix16Surround 6 + M12Mix16Surround 7 + M12Mix16Surround 8 + M12Mix16Surround 9 + M12Mix16Surround 10 + M12Mix16Surround 11 + M12Mix16Surround 12 + M12Mix16Surround 13 + M12Mix16Surround 14 + M12Mix16Surround 15 + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ M12Mix16Surround0 + + Ret + +EndP Mix12Surround16Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix12Surround16Bit + + Mov AL, [SI+0Eh] + Mov Byte Ptr [CS:M12Surround16BitVolume], AL + + Ret + +EndP PreMix12Surround16Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Mix12Panned16BitOffsetTable Label Word + + IndexCounter = 15 + + M12Mix16PannedOffset Macro Index + DW Offset M12Mix16Panned&Index& + EndM + + REPT 16 + M12Mix16PannedOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix12Panned16Bit + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Push [CS:Mix12Panned16BitOffsetTable+BX] + + M12Mix16PannedNext 0 + + RetN + +Pan12Bit16Loop: + M12Mix16PannedNext 16 + + M12Mix16Panned 0 + M12Mix16Panned 1 + M12Mix16Panned 2 + M12Mix16Panned 3 + M12Mix16Panned 4 + M12Mix16Panned 5 + M12Mix16Panned 6 + M12Mix16Panned 7 + M12Mix16Panned 8 + M12Mix16Panned 9 + M12Mix16Panned 10 + M12Mix16Panned 11 + M12Mix16Panned 12 + M12Mix16Panned 13 + M12Mix16Panned 14 + + M12Mix16Panned15: + Add BX, BX + Add ERROR, DELTAERROR + AdC DI, DELTAOFFSET + Mov AX, [BX] + Sub [SI+EXTRAOFFSET], AX + M12Mix16PannedRightVolumeOffset15 EQU $+3 + Mov AX, [BX+1200h] + Sub [SI+MixResolution/8+EXTRAOFFSET], AX + + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ Pan12Bit16Loop + + Ret + +EndP Mix12Panned16Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix12Panned16Bit + + Mov AL, [SI+0Eh] + + IndexCounter = 0 + + PreMix12PannedMacro Macro Index + Mov Byte Ptr [CS:M12Mix16PannedVolume&Index&], AL + EndM + + REPT 17 + PreMix12PannedMacro %IndexCounter + IndexCounter = IndexCounter+1 + EndM + + Mov AL, [SI+0Ch] + Sub AL, [SI+0Eh] + Add AL, AL + + IndexCounter = 0 + + PreMix12PannedMacro2 Macro Index + Mov Byte Ptr [CS:M12Mix16PannedRightVolumeOffset&Index&], AL + EndM + + REPT 16 + PreMix12PannedMacro2 %IndexCounter + IndexCounter = IndexCounter+1 + EndM + + Ret + +EndP PreMix12Panned16Bit + + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + diff --git a/SoundDrivers/M12BITF.INC b/SoundDrivers/M12BITF.INC new file mode 100755 index 0000000..dec5297 --- /dev/null +++ b/SoundDrivers/M12BITF.INC @@ -0,0 +1,49 @@ + + DW Offset UpdateNoLoop, 0, 0, 0, 0 ; Update only + DW Offset UpdateForwardsLoop, 0, 0, 0, 0 + DW Offset UpdatePingPongLoop, 0, 0, 0, 0 + ; Left only + DW Offset MixNoLoop, PreMix12Left8BitF, MFS8Bit, MBS8Bit, Mix12Single8BitF + DW Offset MixForwardsLoop, PreMix12Left8BitF, MFS8Bit, MBS8Bit, Mix12Single8BitF + DW Offset MixPingPongLoop, PreMix12Left8BitF, MFS8Bit, MBS8Bit, Mix12Single8BitF + ; Right only + DW Offset MixNoLoop, PreMix12Right8BitF, MFS8Bit, MBS8Bit, Mix12Single8BitF + DW Offset MixForwardsLoop, PreMix12Right8BitF, MFS8Bit, MBS8Bit, Mix12Single8BitF + DW Offset MixPingPongLoop, PreMix12Right8BitF, MFS8Bit, MBS8Bit, Mix12Single8BitF + ; Central + DW Offset MixNoLoop, PreMix12Central8BitF, MFS8Bit, MBS8Bit, Mix12Central8BitF + DW Offset MixForwardsLoop, PreMix12Central8BitF, MFS8Bit, MBS8Bit, Mix12Central8BitF + DW Offset MixPingPongLoop, PreMix12Central8BitF, MFS8Bit, MBS8Bit, Mix12Central8BitF + ; Stereo + DW Offset MixNoLoop, PreMix12Panned8BitF, MFS8Bit, MBS8Bit, Mix12Panned8BitF + DW Offset MixForwardsLoop, PreMix12Panned8BitF, MFS8Bit, MBS8Bit, Mix12Panned8BitF + DW Offset MixPingPongLoop, PreMix12Panned8BitF, MFS8Bit, MBS8Bit, Mix12Panned8BitF + ; Surround + DW Offset MixNoLoop, PreMix12Surround8BitF, MFS8Bit, MBS8Bit, Mix12Surround8BitF + DW Offset MixForwardsLoop, PreMix12Surround8BitF, MFS8Bit, MBS8Bit, Mix12Surround8BitF + DW Offset MixPingPongLoop, PreMix12Surround8BitF, MFS8Bit, MBS8Bit, Mix12Surround8BitF + + ; 16 bit tables + DW Offset UpdateNoLoop, 0, 0, 0, 0 ; Update only + DW Offset UpdateForwardsLoop, 0, 0, 0, 0 + DW Offset UpdatePingPongLoop, 0, 0, 0, 0 + ; Left only + DW Offset MixNoLoop, PreMix12Left16BitF, MFS16Bit, MBS16Bit, Mix12Single16BitF + DW Offset MixForwardsLoop, PreMix12Left16BitF, MFS16Bit, MBS16Bit, Mix12Single16BitF + DW Offset MixPingPongLoop, PreMix12Left16BitF, MFS16Bit, MBS16Bit, Mix12Single16BitF + ; Right only + DW Offset MixNoLoop, PreMix12Right16BitF, MFS16Bit, MBS16Bit, Mix12Single16BitF + DW Offset MixForwardsLoop, PreMix12Right16BitF, MFS16Bit, MBS16Bit, Mix12Single16BitF + DW Offset MixPingPongLoop, PreMix12Right16BitF, MFS16Bit, MBS16Bit, Mix12Single16BitF + ; Central + DW Offset MixNoLoop, PreMix12Central16BitF, MFS16Bit, MBS16Bit, Mix12Central16BitF + DW Offset MixForwardsLoop, PreMix12Central16BitF, MFS16Bit, MBS16Bit, Mix12Central16BitF + DW Offset MixPingPongLoop, PreMix12Central16BitF, MFS16Bit, MBS16Bit, Mix12Central16BitF + ; Stereo + DW Offset MixNoLoop, PreMix12Panned16BitF, MFS16Bit, MBS16Bit, Mix12Panned16BitF + DW Offset MixForwardsLoop, PreMix12Panned16BitF, MFS16Bit, MBS16Bit, Mix12Panned16BitF + DW Offset MixPingPongLoop, PreMix12Panned16BitF, MFS16Bit, MBS16Bit, Mix12Panned16BitF + ; Surround + DW Offset MixNoLoop, PreMix12Surround16BitF, MFS16Bit, MBS16Bit, Mix12Surround16BitF + DW Offset MixForwardsLoop, PreMix12Surround16BitF, MFS16Bit, MBS16Bit, Mix12Surround16BitF + DW Offset MixPingPongLoop, PreMix12Surround16BitF, MFS16Bit, MBS16Bit, Mix12Surround16BitF diff --git a/SoundDrivers/M12BITF.MIX b/SoundDrivers/M12BITF.MIX new file mode 100755 index 0000000..75bd69b --- /dev/null +++ b/SoundDrivers/M12BITF.MIX @@ -0,0 +1,807 @@ + + ; Different mixing routines required: + ; Left } shared + ; Right } + ; Central + ; Surround + ; Panned ; Each requires 8 bit and 16 bit + ; Single output - for Mono, pure left/pure right + +Get8BitFWaveform Macro + Mov AL, [ES:DI] + Add BL, 80h + Add AL, 80h + Add BL, AL + RCR BL, 1 + Sub BL, 80h +EndM + +Get16BitFWaveform Macro + Mov AL, [ES:EDI+EDI+1] + Add BL, 80h + Add AL, 80h + Add BL, AL + RCR BL, 1 + Sub BL, 80h + +EndM + +M12Mix8FSingle Macro Index + +M12Mix8FSingle&Index&: + Get8BitFWaveForm + + Add ERROR, DELTAERROR + Mov AX, [EBX+EBX] + AdC DI, DELTAOFFSET ;; 1 + Sub [SI+(Index-15)*MixResolution/4+EXTRAOFFSET], AX ;; 3 + +EndM + +M12Mix8FCentral Macro Index + +M12Mix8FCentral&Index&: + Get8BitFWaveform + + Add ERROR, DELTAERROR ;; 1 + Mov AX, [EBX+EBX] ;; 2 + AdC DI, DELTAOFFSET ;; 1 + Sub [SI+(Index-15)*MixResolution/4+EXTRAOFFSET], AX ;; 3 + Sub [SI+(Index-15)*MixResolution/4+MixResolution/8+EXTRAOFFSET], AX ;; 3 + +EndM + +M12Mix8FSurround Macro Index + +M12Mix8FSurround&Index&: + Get8BitFWaveform + + Add ERROR, DELTAERROR ;; 1 + Mov AX, [EBX+EBX] ;; 2 + AdC DI, DELTAOFFSET ;; 1 + Sub [SI+(Index-15)*MixResolution/4+EXTRAOFFSET], AX ;; 3 + Add [SI+(Index-15)*MixResolution/4+MixResolution/8+EXTRAOFFSET], AX ;; 3 + +EndM + +M12Mix8FPanned Macro Index + +M12Mix8FPanned&Index&: + Get8BitFWaveform + + Add ERROR, DELTAERROR + AdC DI, DELTAOFFSET + Mov AX, [EBX+EBX] + Sub [SI+(Index-15)*MixResolution/4+EXTRAOFFSET], AX + +M12Mix8FPannedRightVolumeOffset&Index& EQU $+4 + Mov AX, [EBX+EBX+1200h] + Sub [SI+(Index-15)*MixResolution/4+MixResolution/8+EXTRAOFFSET], AX + +EndM + +M12Mix16FSingle Macro Index + +M12Mix16FSingle&Index&: + Get16BitFWaveForm + + Add ERROR, DELTAERROR + Mov AX, [EBX+EBX] + AdC DI, DELTAOFFSET + Sub [SI+(Index-15)*MixResolution/4+EXTRAOFFSET], AX + +EndM + +M12Mix16FCentral Macro Index + +M12Mix16FCentral&Index&: + Get16BitFWaveform + + Add ERROR, DELTAERROR + Mov AX, [EBX+EBX] + AdC DI, DELTAOFFSET + Sub [SI+(Index-15)*MixResolution/4+EXTRAOFFSET], AX + Sub [SI+(Index-15)*MixResolution/4+MixResolution/8+EXTRAOFFSET], AX + +EndM + +M12Mix16FSurround Macro Index + +M12Mix16FSurround&Index&: + Get16BitFWaveform + + Add ERROR, DELTAERROR + Mov AX, [EBX+EBX] + AdC DI, DELTAOFFSET + Sub [SI+(Index-15)*MixResolution/4+EXTRAOFFSET], AX + Add [SI+(Index-15)*MixResolution/4+MixResolution/8+EXTRAOFFSET], AX + +EndM + + ; Panned output +M12Mix16FPanned Macro Index + +M12Mix16FPanned&Index&: + Get16BitFWaveform + + Add ERROR, DELTAERROR + AdC DI, DELTAOFFSET + Mov AX, [EBX+EBX] + Sub [SI+(Index-15)*MixResolution/4+EXTRAOFFSET], AX + +M12Mix16FPannedRightVolumeOffset&Index& EQU $+4 + Mov AX, [EBX+EBX+1200h] + Sub [SI+(Index-15)*MixResolution/4+MixResolution/8+EXTRAOFFSET], AX + +EndM + +;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ + +Mix12Single8BitFOffsetTable Label Word + + IndexCounter = 15 + + M12Mix8FSingleOffset Macro Index + DW Offset M12Mix8FSingle&Index& + EndM + + REPT 16 + M12Mix8FSingleOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix12Single8BitF + ; AX = count... + + ; Number of times to loop = (Count-1) / 16 + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Push [CS:Mix12Single8BitFOffsetTable+BX] + +Mix12Single8BitFVolume EQU $+3 + Mov EBX, 0 + + Mov BL, [ES:DI] + + RetN + + M12Mix8FSingle 0 + M12Mix8FSingle 1 + M12Mix8FSingle 2 + M12Mix8FSingle 3 + M12Mix8FSingle 4 + M12Mix8FSingle 5 + M12Mix8FSingle 6 + M12Mix8FSingle 7 + M12Mix8FSingle 8 + M12Mix8FSingle 9 + M12Mix8FSingle 10 + M12Mix8FSingle 11 + M12Mix8FSingle 12 + M12Mix8FSingle 13 + M12Mix8FSingle 14 + M12Mix8FSingle 15 + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ M12Mix8FSingle0 + + Ret + +EndP Mix12Single8BitF + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix12Left8BitF + + Mov AL, [SI+0Eh] + Mov Byte Ptr [CS:Mix12Single8BitFVolume], AL + + Ret + +EndP PreMix12Left8BitF + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix12Right8BitF + + Add MixBufferOffset, MixResolution/8 + Mov AL, [SI+0Ch] + Mov Byte Ptr [CS:Mix12Single8BitFVolume], AL + + Ret + +EndP PreMix12Right8BitF + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Mix12Central8BitFOffsetTable Label Word + + IndexCounter = 15 + + M12Mix8FCentralOffset Macro Index + DW Offset M12Mix8FCentral&Index& + EndM + + REPT 16 + M12Mix8FCentralOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix12Central8BitF + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Push [CS:Mix12Central8BitFOffsetTable+BX] + +Mix12Central8BitFVolume EQU $+3 + Mov EBX, 0 + + Mov BL, [ES:DI] + + RetN + + M12Mix8FCentral 0 + M12Mix8FCentral 1 + M12Mix8FCentral 2 + M12Mix8FCentral 3 + M12Mix8FCentral 4 + M12Mix8FCentral 5 + M12Mix8FCentral 6 + M12Mix8FCentral 7 + M12Mix8FCentral 8 + M12Mix8FCentral 9 + M12Mix8FCentral 10 + M12Mix8FCentral 11 + M12Mix8FCentral 12 + M12Mix8FCentral 13 + M12Mix8FCentral 14 + M12Mix8FCentral 15 + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ M12Mix8FCentral0 + + Ret + +EndP Mix12Central8BitF + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix12Central8BitF + + Mov AL, [SI+0Eh] + Mov Byte Ptr [CS:Mix12Central8BitFVolume], AL + + Ret + +EndP PreMix12Central8BitF + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Mix12Surround8BitFOffsetTable Label Word + + IndexCounter = 15 + + M12Mix8FSurroundOffset Macro Index + DW Offset M12Mix8FSurround&Index& + EndM + + REPT 16 + M12Mix8FSurroundOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix12Surround8BitF + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Push [CS:Mix12Surround8BitFOffsetTable+BX] + +Mix12Surround8BitFVolume EQU $+3 + Mov EBX, 0 + + Mov BL, [ES:DI] + + RetN + + M12Mix8FSurround 0 + M12Mix8FSurround 1 + M12Mix8FSurround 2 + M12Mix8FSurround 3 + M12Mix8FSurround 4 + M12Mix8FSurround 5 + M12Mix8FSurround 6 + M12Mix8FSurround 7 + M12Mix8FSurround 8 + M12Mix8FSurround 9 + M12Mix8FSurround 10 + M12Mix8FSurround 11 + M12Mix8FSurround 12 + M12Mix8FSurround 13 + M12Mix8FSurround 14 + M12Mix8FSurround 15 + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ M12Mix8FSurround0 + + Ret + +EndP Mix12Surround8BitF + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix12Surround8BitF + + Mov AL, [SI+0Eh] + Mov Byte Ptr [CS:Mix12Surround8BitFVolume], AL + + Ret + +EndP PreMix12Surround8BitF + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Mix12Panned8BitFOffsetTable Label Word + + IndexCounter = 15 + + M12Mix8FPannedOffset Macro Index + DW Offset M12Mix8FPanned&Index& + EndM + + REPT 16 + M12Mix8FPannedOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix12Panned8BitF + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Push [CS:Mix12Panned8BitFOffsetTable+BX] + +Mix12Panned8BitFVolume EQU $+3 + Mov EBX, 0 + + Mov BL, [ES:DI] + + RetN + + M12Mix8FPanned 0 + M12Mix8FPanned 1 + M12Mix8FPanned 2 + M12Mix8FPanned 3 + M12Mix8FPanned 4 + M12Mix8FPanned 5 + M12Mix8FPanned 6 + M12Mix8FPanned 7 + M12Mix8FPanned 8 + M12Mix8FPanned 9 + M12Mix8FPanned 10 + M12Mix8FPanned 11 + M12Mix8FPanned 12 + M12Mix8FPanned 13 + M12Mix8FPanned 14 + M12Mix8FPanned 15 + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ M12Mix8FPanned0 + + Ret + +EndP Mix12Panned8BitF + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix12Panned8BitF + + Mov AL, [SI+0Eh] + Mov AL, [SI+0Eh] + Mov Byte Ptr [CS:Mix12Panned8BitFVolume], AL + + Xor AL, AL + Mov AH, [SI+0Ch] + Sub AH, [SI+0Eh] + Add AH, AH + MovSX EAX, AX + + IndexCounter = 0 + + PreMix12Panned8BitFMacro2 Macro Index + Mov DWord Ptr [CS:M12Mix8FPannedRightVolumeOffset&Index&], EAX + EndM + + REPT 16 + PreMix12Panned8BitFMacro2 %IndexCounter + IndexCounter = IndexCounter+1 + EndM + + Ret + +EndP PreMix12Panned8BitF + +;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ + +Mix12Single16BitFOffsetTable Label Word + + IndexCounter = 15 + + M12Mix16FSingleOffset Macro Index + DW Offset M12Mix16FSingle&Index& + EndM + + REPT 16 + M12Mix16FSingleOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix12Single16BitF + ; AX = count... + + ; Number of times to loop = (Count-1) / 16 + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Push [CS:Mix12Single16BitFOffsetTable+BX] + +Mix12Single16BitFVolume EQU $+3 + Mov EBX, 0 + + Mov BL, [ES:EDI+EDI+1] + + RetN + + M12Mix16FSingle 0 + M12Mix16FSingle 1 + M12Mix16FSingle 2 + M12Mix16FSingle 3 + M12Mix16FSingle 4 + M12Mix16FSingle 5 + M12Mix16FSingle 6 + M12Mix16FSingle 7 + M12Mix16FSingle 8 + M12Mix16FSingle 9 + M12Mix16FSingle 10 + M12Mix16FSingle 11 + M12Mix16FSingle 12 + M12Mix16FSingle 13 + M12Mix16FSingle 14 + M12Mix16FSingle 15 + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ M12Mix16FSingle0 + + Ret + +EndP Mix12Single16BitF + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix12Left16BitF + + Mov AL, [SI+0Eh] + Mov Byte Ptr [CS:Mix12Single16BitFVolume], AL + + Ret + +EndP PreMix12Left16BitF + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix12Right16BitF + + Add MixBufferOffset, MixResolution/8 + Mov AL, [SI+0Ch] + Mov Byte Ptr [CS:Mix12Single16BitFVolume], AL + + Ret + +EndP PreMix12Right16BitF + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Mix12Central16BitFOffsetTable Label Word + + IndexCounter = 15 + + M12Mix16FCentralOffset Macro Index + DW Offset M12Mix16FCentral&Index& + EndM + + REPT 16 + M12Mix16FCentralOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix12Central16BitF + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Push [CS:Mix12Central16BitFOffsetTable+BX] + +Mix12Central16BitFVolume EQU $+3 + Mov EBX, 0 + + Mov BL, [ES:EDI+EDI+1] + + RetN + + M12Mix16FCentral 0 + M12Mix16FCentral 1 + M12Mix16FCentral 2 + M12Mix16FCentral 3 + M12Mix16FCentral 4 + M12Mix16FCentral 5 + M12Mix16FCentral 6 + M12Mix16FCentral 7 + M12Mix16FCentral 8 + M12Mix16FCentral 9 + M12Mix16FCentral 10 + M12Mix16FCentral 11 + M12Mix16FCentral 12 + M12Mix16FCentral 13 + M12Mix16FCentral 14 + M12Mix16FCentral 15 + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ M12Mix16FCentral0 + + Ret + +EndP Mix12Central16BitF + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix12Central16BitF + + Mov AL, [SI+0Eh] + Mov Byte Ptr [CS:Mix12Central16BitFVolume], AL + + Ret + +EndP PreMix12Central16BitF + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Mix12Surround16BitFOffsetTable Label Word + + IndexCounter = 15 + + M12Mix16FSurroundOffset Macro Index + DW Offset M12Mix16FSurround&Index& + EndM + + REPT 16 + M12Mix16FSurroundOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix12Surround16BitF + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Push [CS:Mix12Surround16BitFOffsetTable+BX] + +Mix12Surround16BitFVolume EQU $+3 + Mov EBX, 0 + + Mov BL, [ES:EDI+EDI+1] + + RetN + + M12Mix16FSurround 0 + M12Mix16FSurround 1 + M12Mix16FSurround 2 + M12Mix16FSurround 3 + M12Mix16FSurround 4 + M12Mix16FSurround 5 + M12Mix16FSurround 6 + M12Mix16FSurround 7 + M12Mix16FSurround 8 + M12Mix16FSurround 9 + M12Mix16FSurround 10 + M12Mix16FSurround 11 + M12Mix16FSurround 12 + M12Mix16FSurround 13 + M12Mix16FSurround 14 + M12Mix16FSurround 15 + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ M12Mix16FSurround0 + + Ret + +EndP Mix12Surround16BitF + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix12Surround16BitF + + Mov AL, [SI+0Eh] + Mov Byte Ptr [CS:Mix12Surround16BitFVolume], AL + + Ret + +EndP PreMix12Surround16BitF + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Mix12Panned16BitFOffsetTable Label Word + + IndexCounter = 15 + + M12Mix16FPannedOffset Macro Index + DW Offset M12Mix16FPanned&Index& + EndM + + REPT 16 + M12Mix16FPannedOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix12Panned16BitF + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Push [CS:Mix12Panned16BitFOffsetTable+BX] + +Mix12Panned16BitFVolume EQU $+3 + Mov EBX, 0 + + Mov BL, [ES:EDI+EDI+1] + + RetN + +Pan12BitF16Loop: + M12Mix16FPanned 0 + M12Mix16FPanned 1 + M12Mix16FPanned 2 + M12Mix16FPanned 3 + M12Mix16FPanned 4 + M12Mix16FPanned 5 + M12Mix16FPanned 6 + M12Mix16FPanned 7 + M12Mix16FPanned 8 + M12Mix16FPanned 9 + M12Mix16FPanned 10 + M12Mix16FPanned 11 + M12Mix16FPanned 12 + M12Mix16FPanned 13 + M12Mix16FPanned 14 + M12Mix16FPanned 15 + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ Pan12BitF16Loop + + Ret + +EndP Mix12Panned16BitF + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix12Panned16BitF + + Mov AL, [SI+0Eh] + Mov Byte Ptr [CS:Mix12Panned16BitFVolume], AL + + Xor AL, AL + Mov AH, [SI+0Ch] + Sub AH, [SI+0Eh] + Add AH, AH + MovSX EAX, AX + + IndexCounter = 0 + + PreMix12PannedMacro2 Macro Index + Mov DWord Ptr [CS:M12Mix16FPannedRightVolumeOffset&Index&], EAX + EndM + + REPT 16 + PreMix12PannedMacro2 %IndexCounter + IndexCounter = IndexCounter+1 + EndM + + Ret + +EndP PreMix12Panned16BitF + + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + diff --git a/SoundDrivers/M12BITI.INC b/SoundDrivers/M12BITI.INC new file mode 100755 index 0000000..b9cd987 --- /dev/null +++ b/SoundDrivers/M12BITI.INC @@ -0,0 +1,49 @@ + + DW Offset UpdateNoLoop, 0, 0, 0, 0 ; Update only + DW Offset UpdateForwardsLoop, 0, 0, 0, 0 + DW Offset UpdatePingPongLoop, 0, 0, 0, 0 + ; Left only + DW Offset MixNoLoop, PreMix12Left8BitI, MFS8Bit, MBS8Bit, Mix12Single8BitI + DW Offset MixForwardsLoop, PreMix12Left8BitI, MFS8Bit, MBS8Bit, Mix12Single8BitI + DW Offset MixPingPongLoop, PreMix12Left8BitI, MFS8Bit, MBS8Bit, Mix12Single8BitI + ; Right only + DW Offset MixNoLoop, PreMix12Right8BitI, MFS8Bit, MBS8Bit, Mix12Single8BitI + DW Offset MixForwardsLoop, PreMix12Right8BitI, MFS8Bit, MBS8Bit, Mix12Single8BitI + DW Offset MixPingPongLoop, PreMix12Right8BitI, MFS8Bit, MBS8Bit, Mix12Single8BitI + ; Central + DW Offset MixNoLoop, PreMix12Central8BitI, MFS8Bit, MBS8Bit, Mix12Central8BitI + DW Offset MixForwardsLoop, PreMix12Central8BitI, MFS8Bit, MBS8Bit, Mix12Central8BitI + DW Offset MixPingPongLoop, PreMix12Central8BitI, MFS8Bit, MBS8Bit, Mix12Central8BitI + ; Stereo + DW Offset MixNoLoop, PreMix12Panned8BitI, MFS8Bit, MBS8Bit, Mix12Panned8BitI + DW Offset MixForwardsLoop, PreMix12Panned8BitI, MFS8Bit, MBS8Bit, Mix12Panned8BitI + DW Offset MixPingPongLoop, PreMix12Panned8BitI, MFS8Bit, MBS8Bit, Mix12Panned8BitI + ; Surround + DW Offset MixNoLoop, PreMix12Surround8BitI, MFS8Bit, MBS8Bit, Mix12Surround8BitI + DW Offset MixForwardsLoop, PreMix12Surround8BitI, MFS8Bit, MBS8Bit, Mix12Surround8BitI + DW Offset MixPingPongLoop, PreMix12Surround8BitI, MFS8Bit, MBS8Bit, Mix12Surround8BitI + + ; 16 bit tables + DW Offset UpdateNoLoop, 0, 0, 0, 0 ; Update only + DW Offset UpdateForwardsLoop, 0, 0, 0, 0 + DW Offset UpdatePingPongLoop, 0, 0, 0, 0 + ; Left only + DW Offset MixNoLoop, PreMix12Left16BitI, MFS16Bit, MBS16Bit, Mix12Single16BitI + DW Offset MixForwardsLoop, PreMix12Left16BitI, MFS16Bit, MBS16Bit, Mix12Single16BitI + DW Offset MixPingPongLoop, PreMix12Left16BitI, MFS16Bit, MBS16Bit, Mix12Single16BitI + ; Right only + DW Offset MixNoLoop, PreMix12Right16BitI, MFS16Bit, MBS16Bit, Mix12Single16BitI + DW Offset MixForwardsLoop, PreMix12Right16BitI, MFS16Bit, MBS16Bit, Mix12Single16BitI + DW Offset MixPingPongLoop, PreMix12Right16BitI, MFS16Bit, MBS16Bit, Mix12Single16BitI + ; Central + DW Offset MixNoLoop, PreMix12Central16BitI, MFS16Bit, MBS16Bit, Mix12Central16BitI + DW Offset MixForwardsLoop, PreMix12Central16BitI, MFS16Bit, MBS16Bit, Mix12Central16BitI + DW Offset MixPingPongLoop, PreMix12Central16BitI, MFS16Bit, MBS16Bit, Mix12Central16BitI + ; Stereo + DW Offset MixNoLoop, PreMix12Panned16BitI, MFS16Bit, MBS16Bit, Mix12Panned16BitI + DW Offset MixForwardsLoop, PreMix12Panned16BitI, MFS16Bit, MBS16Bit, Mix12Panned16BitI + DW Offset MixPingPongLoop, PreMix12Panned16BitI, MFS16Bit, MBS16Bit, Mix12Panned16BitI + ; Surround + DW Offset MixNoLoop, PreMix12Surround16BitI, MFS16Bit, MBS16Bit, Mix12Surround16BitI + DW Offset MixForwardsLoop, PreMix12Surround16BitI, MFS16Bit, MBS16Bit, Mix12Surround16BitI + DW Offset MixPingPongLoop, PreMix12Surround16BitI, MFS16Bit, MBS16Bit, Mix12Surround16BitI diff --git a/SoundDrivers/M12BITI.MIX b/SoundDrivers/M12BITI.MIX new file mode 100755 index 0000000..5bc839b --- /dev/null +++ b/SoundDrivers/M12BITI.MIX @@ -0,0 +1,866 @@ + + ; Different mixing routines required: + ; Left } shared + ; Right } + ; Central + ; Surround + ; Panned ; Each requires 8 bit and 16 bit + ; Single output - for Mono, pure left/pure right + + ; Interpolation = [DI+1]*Error + [DI]*(1-Error) + ; = [DI+1]*Error + [DI] - [DI]*Error + ; = Error*([DI+1]-[DI]) + [DI] + + +Get8BitIWaveform Macro + MovSX EBX, Byte Ptr [ES:DI] ; 5 + MovSX EAX, Byte Ptr [ES:DI+1] ; 5 + Sub EAX, EBX ; 2 + IMul EAX, ECX + SAR EAX, 16 ; 3 + Add BL, AL ; 1 + +EndM + +Get16BitIWaveform Macro + MovSX EBX, Byte Ptr [ES:EDI+EDI+1] ; 5 + MovSX EAX, Byte Ptr [ES:EDI+EDI+3] ; 5 + Sub EAX, EBX ; 2 + IMul EAX, ECX + SAR EAX, 16 ; 3 + Add BL, AL ; 1 + +EndM + +M12Mix8ISingle Macro Index + +M12Mix8ISingle&Index&: + Get8BitIWaveform + +M12Mix8ISingleVolume&Index& EQU $+1 + Mov BH, 12h + Add BX, BX + + Add ERROR, DELTAERROR + Mov AX, [BX] + AdC DI, DELTAOFFSET ;; 1 + Sub [SI+(Index-15)*MixResolution/4+EXTRAOFFSET], AX ;; 3 + +EndM + +M12Mix8ICentral Macro Index + +M12Mix8ICentral&Index&: + Get8BitIWaveform + +M12Mix8ICentralVolume&Index& EQU $+1 + Mov BH, 12h + Add BX, BX + + Add ERROR, DELTAERROR ;; 1 + Mov AX, [BX] ;; 2 + AdC DI, DELTAOFFSET ;; 1 + Sub [SI+(Index-15)*MixResolution/4+EXTRAOFFSET], AX ;; 3 + Sub [SI+(Index-15)*MixResolution/4+MixResolution/8+EXTRAOFFSET], AX ;; 3 + +EndM + +M12Mix8ISurround Macro Index + +M12Mix8ISurround&Index&: + Get8BitIWaveform + +M12Mix8ISurroundVolume&Index& EQU $+1 + Mov BH, 12h + Add BX, BX + + Add ERROR, DELTAERROR ;; 1 + Mov AX, [BX] ;; 2 + AdC DI, DELTAOFFSET ;; 1 + Sub [SI+(Index-15)*MixResolution/4+EXTRAOFFSET], AX ;; 3 + Add [SI+(Index-15)*MixResolution/4+MixResolution/8+EXTRAOFFSET], AX ;; 3 + +EndM + +M12Mix8IPanned Macro Index + +M12Mix8IPanned&Index&: + Get8BitIWaveform + +M12Mix8IPannedVolume&Index& EQU $+1 + Mov BH, 12h + Add BX, BX + + Add ERROR, DELTAERROR + AdC DI, DELTAOFFSET + Mov AX, [BX] + Sub [SI+(Index-15)*MixResolution/4+EXTRAOFFSET], AX + +M12Mix8IPannedRightVolumeOffset&Index& EQU $+3 + Mov AX, [BX+1200h] + Sub [SI+(Index-15)*MixResolution/4+MixResolution/8+EXTRAOFFSET], AX + +EndM + +M12Mix16ISingle Macro Index + +M12Mix16ISingle&Index&: + Get16BitIWaveForm + +M12Mix16ISingleVolume&Index& EQU $+1 + Mov BH, 12h + Add BX, BX + + Add ERROR, DELTAERROR + Mov AX, [BX] + AdC DI, DELTAOFFSET + Sub [SI+(Index-15)*MixResolution/4+EXTRAOFFSET], AX + +EndM + +M12Mix16ICentral Macro Index + +M12Mix16ICentral&Index&: + Get16BitIWaveform + +M12Mix16ICentralVolume&Index& EQU $+1 + Mov BH, 12h + Add BX, BX + + Add ERROR, DELTAERROR + Mov AX, [BX] + AdC DI, DELTAOFFSET + Sub [SI+(Index-15)*MixResolution/4+EXTRAOFFSET], AX + Sub [SI+(Index-15)*MixResolution/4+MixResolution/8+EXTRAOFFSET], AX + +EndM + +M12Mix16ISurround Macro Index + +M12Mix16ISurround&Index&: + Get16BitIWaveform + +M12Mix16ISurroundVolume&Index& EQU $+1 + Mov BH, 12h + Add BX, BX + + Add ERROR, DELTAERROR + Mov AX, [BX] + AdC DI, DELTAOFFSET + Sub [SI+(Index-15)*MixResolution/4+EXTRAOFFSET], AX + Add [SI+(Index-15)*MixResolution/4+MixResolution/8+EXTRAOFFSET], AX + +EndM + + ; Panned output +M12Mix16IPanned Macro Index + +M12Mix16IPanned&Index&: + Get16BitIWaveform + +M12Mix16IPannedVolume&Index& EQU $+1 + Mov BH, 12h + Add BX, BX + + Add ERROR, DELTAERROR + AdC DI, DELTAOFFSET + Mov AX, [BX] + Sub [SI+(Index-15)*MixResolution/4+EXTRAOFFSET], AX + +M12Mix16IPannedRightVolumeOffset&Index& EQU $+3 + Mov AX, [BX+1200h] + Sub [SI+(Index-15)*MixResolution/4+MixResolution/8+EXTRAOFFSET], AX + +EndM + +;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ + +Mix12Single8BitIOffsetTable Label Word + + IndexCounter = 15 + + M12Mix8ISingleOffset Macro Index + DW Offset M12Mix8ISingle&Index& + EndM + + REPT 16 + M12Mix8ISingleOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix12Single8BitI + ; AX = count... + + ; Number of times to loop = (Count-1) / 16 + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Jmp [CS:Mix12Single8BitIOffsetTable+BX] + + M12Mix8ISingle 0 + M12Mix8ISingle 1 + M12Mix8ISingle 2 + M12Mix8ISingle 3 + M12Mix8ISingle 4 + M12Mix8ISingle 5 + M12Mix8ISingle 6 + M12Mix8ISingle 7 + M12Mix8ISingle 8 + M12Mix8ISingle 9 + M12Mix8ISingle 10 + M12Mix8ISingle 11 + M12Mix8ISingle 12 + M12Mix8ISingle 13 + M12Mix8ISingle 14 + M12Mix8ISingle 15 + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ M12Mix8ISingle0 + + Ret + +EndP Mix12Single8BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix12Left8BitI + + Mov AL, [SI+0Eh] + +PreMix12Left8BitI1: + + IndexCounter = 0 + + PreMix12Single8BitIMacro Macro Index + Mov Byte Ptr [CS:M12Mix8ISingleVolume&Index&], AL + EndM + + REPT 16 + PreMix12Single8BitIMacro %IndexCounter + IndexCounter = IndexCounter+1 + EndM + + Ret + +EndP PreMix12Left8BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix12Right8BitI + + Add MixBufferOffset, MixResolution/8 + Mov AL, [SI+0Ch] + Jmp PreMix12Left8BitI1 + + Ret + +EndP PreMix12Right8BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Mix12Central8BitIOffsetTable Label Word + + IndexCounter = 15 + + M12Mix8ICentralOffset Macro Index + DW Offset M12Mix8ICentral&Index& + EndM + + REPT 16 + M12Mix8ICentralOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix12Central8BitI + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Jmp [CS:Mix12Central8BitIOffsetTable+BX] + + M12Mix8ICentral 0 + M12Mix8ICentral 1 + M12Mix8ICentral 2 + M12Mix8ICentral 3 + M12Mix8ICentral 4 + M12Mix8ICentral 5 + M12Mix8ICentral 6 + M12Mix8ICentral 7 + M12Mix8ICentral 8 + M12Mix8ICentral 9 + M12Mix8ICentral 10 + M12Mix8ICentral 11 + M12Mix8ICentral 12 + M12Mix8ICentral 13 + M12Mix8ICentral 14 + M12Mix8ICentral 15 + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ M12Mix8ICentral0 + + Ret + +EndP Mix12Central8BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix12Central8BitI + + Mov AL, [SI+0Eh] + + IndexCounter = 0 + + PreMix12Central8BitIMacro Macro Index + Mov Byte Ptr [CS:M12Mix8ICentralVolume&Index&], AL + EndM + + REPT 16 + PreMix12Central8BitIMacro %IndexCounter + IndexCounter = IndexCounter+1 + EndM + + Ret + +EndP PreMix12Central8BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Mix12Surround8BitIOffsetTable Label Word + + IndexCounter = 15 + + M12Mix8ISurroundOffset Macro Index + DW Offset M12Mix8ISurround&Index& + EndM + + REPT 16 + M12Mix8ISurroundOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix12Surround8BitI + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Jmp [CS:Mix12Surround8BitIOffsetTable+BX] + + M12Mix8ISurround 0 + M12Mix8ISurround 1 + M12Mix8ISurround 2 + M12Mix8ISurround 3 + M12Mix8ISurround 4 + M12Mix8ISurround 5 + M12Mix8ISurround 6 + M12Mix8ISurround 7 + M12Mix8ISurround 8 + M12Mix8ISurround 9 + M12Mix8ISurround 10 + M12Mix8ISurround 11 + M12Mix8ISurround 12 + M12Mix8ISurround 13 + M12Mix8ISurround 14 + M12Mix8ISurround 15 + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ M12Mix8ISurround0 + + Ret + +EndP Mix12Surround8BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix12Surround8BitI + + Mov AL, [SI+0Eh] + + IndexCounter = 0 + + PreMix12Surround8BitIMacro Macro Index + Mov Byte Ptr [CS:M12Mix8ISurroundVolume&Index&], AL + EndM + + REPT 16 + PreMix12Surround8BitIMacro %IndexCounter + IndexCounter = IndexCounter+1 + EndM + + Ret + +EndP PreMix12Surround8BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Mix12Panned8BitIOffsetTable Label Word + + IndexCounter = 15 + + M12Mix8IPannedOffset Macro Index + DW Offset M12Mix8IPanned&Index& + EndM + + REPT 16 + M12Mix8IPannedOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix12Panned8BitI + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Jmp [CS:Mix12Panned8BitIOffsetTable+BX] + + M12Mix8IPanned 0 + M12Mix8IPanned 1 + M12Mix8IPanned 2 + M12Mix8IPanned 3 + M12Mix8IPanned 4 + M12Mix8IPanned 5 + M12Mix8IPanned 6 + M12Mix8IPanned 7 + M12Mix8IPanned 8 + M12Mix8IPanned 9 + M12Mix8IPanned 10 + M12Mix8IPanned 11 + M12Mix8IPanned 12 + M12Mix8IPanned 13 + M12Mix8IPanned 14 + M12Mix8IPanned 15 + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ M12Mix8IPanned0 + + Ret + +EndP Mix12Panned8BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix12Panned8BitI + + Mov AL, [SI+0Eh] + + IndexCounter = 0 + + PreMix12Panned8BitIMacro Macro Index + Mov Byte Ptr [CS:M12Mix8IPannedVolume&Index&], AL + EndM + + REPT 16 + PreMix12Panned8BitIMacro %IndexCounter + IndexCounter = IndexCounter+1 + EndM + + Mov AL, [SI+0Ch] + Sub AL, [SI+0Eh] + Add AL, AL + + IndexCounter = 0 + + PreMix12Panned8BitIMacro2 Macro Index + Mov Byte Ptr [CS:M12Mix8IPannedRightVolumeOffset&Index&], AL + EndM + + REPT 16 + PreMix12Panned8BitIMacro2 %IndexCounter + IndexCounter = IndexCounter+1 + EndM + + Ret + +EndP PreMix12Panned8BitI + +;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ + +Mix12Single16BitIOffsetTable Label Word + + IndexCounter = 15 + + M12Mix16ISingleOffset Macro Index + DW Offset M12Mix16ISingle&Index& + EndM + + REPT 16 + M12Mix16ISingleOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix12Single16BitI + ; AX = count... + + ; Number of times to loop = (Count-1) / 16 + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Jmp [CS:Mix12Single16BitIOffsetTable+BX] + + M12Mix16ISingle 0 + M12Mix16ISingle 1 + M12Mix16ISingle 2 + M12Mix16ISingle 3 + M12Mix16ISingle 4 + M12Mix16ISingle 5 + M12Mix16ISingle 6 + M12Mix16ISingle 7 + M12Mix16ISingle 8 + M12Mix16ISingle 9 + M12Mix16ISingle 10 + M12Mix16ISingle 11 + M12Mix16ISingle 12 + M12Mix16ISingle 13 + M12Mix16ISingle 14 + M12Mix16ISingle 15 + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ M12Mix16ISingle0 + + Ret + +EndP Mix12Single16BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix12Left16BitI + + Mov AL, [SI+0Eh] + +PreMix12Left16BitI1: + + IndexCounter = 0 + + PreMix12Single16BitIMacro Macro Index + Mov Byte Ptr [CS:M12Mix16ISingleVolume&Index&], AL + EndM + + REPT 16 + PreMix12Single16BitIMacro %IndexCounter + IndexCounter = IndexCounter+1 + EndM + + Ret + +EndP PreMix12Left16BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix12Right16BitI + + Add MixBufferOffset, MixResolution/8 + Mov AL, [SI+0Ch] + + Jmp PreMix12Left16BitI1 + +EndP PreMix12Right16BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Mix12Central16BitIOffsetTable Label Word + + IndexCounter = 15 + + M12Mix16ICentralOffset Macro Index + DW Offset M12Mix16ICentral&Index& + EndM + + REPT 16 + M12Mix16ICentralOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix12Central16BitI + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Jmp [CS:Mix12Central16BitIOffsetTable+BX] + + M12Mix16ICentral 0 + M12Mix16ICentral 1 + M12Mix16ICentral 2 + M12Mix16ICentral 3 + M12Mix16ICentral 4 + M12Mix16ICentral 5 + M12Mix16ICentral 6 + M12Mix16ICentral 7 + M12Mix16ICentral 8 + M12Mix16ICentral 9 + M12Mix16ICentral 10 + M12Mix16ICentral 11 + M12Mix16ICentral 12 + M12Mix16ICentral 13 + M12Mix16ICentral 14 + M12Mix16ICentral 15 + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ M12Mix16ICentral0 + + Ret + +EndP Mix12Central16BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix12Central16BitI + + Mov AL, [SI+0Eh] + + IndexCounter = 0 + + PreMix12Central16BitIMacro Macro Index + Mov Byte Ptr [CS:M12Mix16ICentralVolume&Index&], AL + EndM + + REPT 16 + PreMix12Central16BitIMacro %IndexCounter + IndexCounter = IndexCounter+1 + EndM + Ret + +EndP PreMix12Central16BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Mix12Surround16BitIOffsetTable Label Word + + IndexCounter = 15 + + M12Mix16ISurroundOffset Macro Index + DW Offset M12Mix16ISurround&Index& + EndM + + REPT 16 + M12Mix16ISurroundOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix12Surround16BitI + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Jmp [CS:Mix12Surround16BitIOffsetTable+BX] + + M12Mix16ISurround 0 + M12Mix16ISurround 1 + M12Mix16ISurround 2 + M12Mix16ISurround 3 + M12Mix16ISurround 4 + M12Mix16ISurround 5 + M12Mix16ISurround 6 + M12Mix16ISurround 7 + M12Mix16ISurround 8 + M12Mix16ISurround 9 + M12Mix16ISurround 10 + M12Mix16ISurround 11 + M12Mix16ISurround 12 + M12Mix16ISurround 13 + M12Mix16ISurround 14 + M12Mix16ISurround 15 + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ M12Mix16ISurround0 + + Ret + +EndP Mix12Surround16BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix12Surround16BitI + + Mov AL, [SI+0Eh] + + IndexCounter = 0 + + PreMix12Surround16BitIMacro Macro Index + Mov Byte Ptr [CS:M12Mix16ISurroundVolume&Index&], AL + EndM + + REPT 16 + PreMix12Surround16BitIMacro %IndexCounter + IndexCounter = IndexCounter+1 + EndM + + Ret + +EndP PreMix12Surround16BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Mix12Panned16BitIOffsetTable Label Word + + IndexCounter = 15 + + M12Mix16IPannedOffset Macro Index + DW Offset M12Mix16IPanned&Index& + EndM + + REPT 16 + M12Mix16IPannedOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix12Panned16BitI + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Jmp [CS:Mix12Panned16BitIOffsetTable+BX] + +Pan12BitI16Loop: + M12Mix16IPanned 0 + M12Mix16IPanned 1 + M12Mix16IPanned 2 + M12Mix16IPanned 3 + M12Mix16IPanned 4 + M12Mix16IPanned 5 + M12Mix16IPanned 6 + M12Mix16IPanned 7 + M12Mix16IPanned 8 + M12Mix16IPanned 9 + M12Mix16IPanned 10 + M12Mix16IPanned 11 + M12Mix16IPanned 12 + M12Mix16IPanned 13 + M12Mix16IPanned 14 + M12Mix16IPanned 15 + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ Pan12BitI16Loop + + Ret + +EndP Mix12Panned16BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix12Panned16BitI + + Mov AL, [SI+0Eh] + + IndexCounter = 0 + + PreMix12PannedMacro Macro Index + Mov Byte Ptr [CS:M12Mix16IPannedVolume&Index&], AL + EndM + + REPT 16 + PreMix12PannedMacro %IndexCounter + IndexCounter = IndexCounter+1 + EndM + + Mov AL, [SI+0Ch] + Sub AL, [SI+0Eh] + Add AL, AL + + IndexCounter = 0 + + PreMix12PannedMacro2 Macro Index + Mov Byte Ptr [CS:M12Mix16IPannedRightVolumeOffset&Index&], AL + EndM + + REPT 16 + PreMix12PannedMacro2 %IndexCounter + IndexCounter = IndexCounter+1 + EndM + + Ret + +EndP PreMix12Panned16BitI + + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + diff --git a/SoundDrivers/M12BITST.MIX b/SoundDrivers/M12BITST.MIX new file mode 100755 index 0000000..6d87910 --- /dev/null +++ b/SoundDrivers/M12BITST.MIX @@ -0,0 +1,832 @@ + +; 12 bit mixing routines, using Stack Segment. + + ; Different mixing routines required: + ; Left } shared + ; Right } + ; Central + ; Surround + ; Panned ; Each requires 8 bit and 16 bit + ; Single output - for Mono, pure left/pure right + +M12Mix8Single Macro Index + +M12Mix8Single&Index&: + Add ERROR, DELTAERROR ;; 1 + Mov BL, [SP] ;; 1 + AdC DI, DELTAOFFSET ;; 1 + Mov AX, [EBX+EBX] ;; 2 + Sub [SI+(Index-15)*MixResolution/4+EXTRAOFFSET], AX ;; 3 + +EndM + +M12Mix8Central Macro Index + +M12Mix8Central&Index&: + Mov BL, [SP] ;; 2 + Add ERROR, DELTAERROR ;; 1 + Mov AX, [EBX+EBX] ;; 2 + AdC DI, DELTAOFFSET ;; 1 + Sub [SI+(Index-15)*MixResolution/4+EXTRAOFFSET], AX ;; 3 + Sub [SI+(Index-15)*MixResolution/4+MixResolution/8+EXTRAOFFSET], AX ;; 3 + +EndM + +M12Mix8Surround Macro Index + +M12Mix8Surround&Index&: + Mov BL, [SP] ;; 2 + Add ERROR, DELTAERROR ;; 1 + Mov AX, [EBX+EBX] ;; 2 + AdC DI, DELTAOFFSET ;; 1 + Sub [SI+(Index-15)*MixResolution/4+EXTRAOFFSET], AX ;; 3 + Add [SI+(Index-15)*MixResolution/4+MixResolution/8+EXTRAOFFSET], AX ;; 3 + +EndM + + ; Panned output +M12Mix8PannedNext Macro Index + +M12Mix8PannedVolume&Index& EQU $+1 + Mov BH, 12h + Mov BL, [SP] + +EndM + +M12Mix8Panned Macro Index + +M12Mix8Panned&Index&: + Add BX, BX + Add ERROR, DELTAERROR + AdC DI, DELTAOFFSET + Mov AX, [BX] + Sub [SI+(Index-15)*MixResolution/4+EXTRAOFFSET], AX + +M12Mix8PannedRightVolumeOffset&Index& EQU $+3 + Mov AX, [BX+1200h] + + M12Mix8PannedNext %(Index+1) + + Sub [SI+(Index-15)*MixResolution/4+MixResolution/8+EXTRAOFFSET], AX + +EndM + +M12Mix16Single Macro Index + +M12Mix16Single&Index&: + Mov BL, [ES:EDI+EDI+1] + Add ERROR, DELTAERROR + Mov AX, [EBX+EBX] + AdC DI, DELTAOFFSET + Sub [SI+(Index-15)*MixResolution/4+EXTRAOFFSET], AX + +EndM + +M12Mix16Central Macro Index + +M12Mix16Central&Index&: + Mov BL, [ES:EDI+EDI+1] + Add ERROR, DELTAERROR + Mov AX, [EBX+EBX] + AdC DI, DELTAOFFSET + Sub [SI+(Index-15)*MixResolution/4+EXTRAOFFSET], AX + Sub [SI+(Index-15)*MixResolution/4+MixResolution/8+EXTRAOFFSET], AX + +EndM + +M12Mix16Surround Macro Index + +M12Mix16Surround&Index&: + Mov BL, [ES:EDI+EDI+1] + Add ERROR, DELTAERROR + Mov AX, [EBX+EBX] + AdC DI, DELTAOFFSET + Sub [SI+(Index-15)*MixResolution/4+EXTRAOFFSET], AX + Add [SI+(Index-15)*MixResolution/4+MixResolution/8+EXTRAOFFSET], AX + +EndM + + ; Panned output +M12Mix16PannedNext Macro Index + +M12Mix16PannedVolume&Index& EQU $+1 + Mov BH, 12h + Mov BL, [ES:EDI+EDI+1] + +EndM + +M12Mix16Panned Macro Index + +M12Mix16Panned&Index&: + Add BX, BX + Add ERROR, DELTAERROR + AdC DI, DELTAOFFSET + Mov AX, [BX] + Sub [SI+(Index-15)*MixResolution/4+EXTRAOFFSET], AX + +M12Mix16PannedRightVolumeOffset&Index& EQU $+3 + Mov AX, [BX+1200h] + + M12Mix16PannedNext %(Index+1) + + Sub [SI+(Index-15)*MixResolution/4+MixResolution/8+EXTRAOFFSET], AX + +EndM + +;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ + +Mix12Single8BitOffsetTable Label Word + + IndexCounter = 15 + + M12Mix8SingleOffset Macro Index + DW Offset M12Mix8Single&Index& + EndM + + REPT 16 + M12Mix8SingleOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +ALIGN 2 +OldStackSegment DW 0 +OldStackPointer DW 0 +MixingOffset DW 0 + +Proc Mix12Single8Bit + ; AX = count... + + ; Number of times to loop = (Count-1) / 16 + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Mov AX, [CS:Mix12BitSingle8BitOffsetTable+BX] + Mov [CS:OldStackSegment], SS + Mov [CS:OldStackPointer], SP + Mov [CS:MixingOffset], AX + +M12Single8BitVolume EQU $+3 + Mov EBX, 0 ; Set BH = volume + Mov ESP, EDI + Jmp [CS:MixingOffset] + + M12Mix8Single 0 + M12Mix8Single 1 + M12Mix8Single 2 + M12Mix8Single 3 + M12Mix8Single 4 + M12Mix8Single 5 + M12Mix8Single 6 + M12Mix8Single 7 + M12Mix8Single 8 + M12Mix8Single 9 + M12Mix8Single 10 + M12Mix8Single 11 + M12Mix8Single 12 + M12Mix8Single 13 + M12Mix8Single 14 + M12Mix8Single 15 + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ M12Mix8Single0 + + Mov SS, [CS:StackSegment] + Mov SP, [CS:StackPointer] + + Ret + +EndP Mix12Single8Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix12Left8Bit + + Mov AL, [SI+0Eh] + Mov Byte Ptr [CS:M12Single8BitVolume], AL + Ret + +EndP PreMix12Left8Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix12Right8Bit + + Add MixBufferOffset, MixResolution/8 + Mov AL, [SI+0Ch] + Mov Byte Ptr [CS:M12Single8BitVolume], AL + + Ret + +EndP PreMix12Right8Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Mix12Central8BitOffsetTable Label Word + + IndexCounter = 15 + + M12Mix8CentralOffset Macro Index + DW Offset M12Mix8Central&Index& + EndM + + REPT 16 + M12Mix8CentralOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix12Central8Bit + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Mov AX, [CS:Mix12BitSingle8BitOffsetTable+BX] + Mov [CS:OldStackSegment], SS + Mov [CS:OldStackPointer], SP + Mov [CS:MixingOffset], AX + +M12Central8BitVolume EQU $+3 + Mov EBX, 0 ; Set BH = volume + Mov ESP, EDI + Jmp [CS:MixingOffset] + + M12Mix8Central 0 + M12Mix8Central 1 + M12Mix8Central 2 + M12Mix8Central 3 + M12Mix8Central 4 + M12Mix8Central 5 + M12Mix8Central 6 + M12Mix8Central 7 + M12Mix8Central 8 + M12Mix8Central 9 + M12Mix8Central 10 + M12Mix8Central 11 + M12Mix8Central 12 + M12Mix8Central 13 + M12Mix8Central 14 + M12Mix8Central 15 + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ M12Mix8Central0 + + Mov SS, [CS:StackSegment] + Mov SP, [CS:StackPointer] + + Ret + +EndP Mix12Central8Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix12Central8Bit + + Mov AL, [SI+0Eh] + Mov Byte Ptr [CS:M12Central8BitVolume], AL + + Ret + +EndP PreMix12Central8Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Mix12Surround8BitOffsetTable Label Word + + IndexCounter = 15 + + M12Mix8SurroundOffset Macro Index + DW Offset M12Mix8Surround&Index& + EndM + + REPT 16 + M12Mix8SurroundOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix12Surround8Bit + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Push [CS:Mix12Surround8BitOffsetTable+BX] + +M12Surround8BitVolume EQU $+3 + Mov EBX, 0 ; Set BH = volume + + + RetN + + M12Mix8Surround 0 + M12Mix8Surround 1 + M12Mix8Surround 2 + M12Mix8Surround 3 + M12Mix8Surround 4 + M12Mix8Surround 5 + M12Mix8Surround 6 + M12Mix8Surround 7 + M12Mix8Surround 8 + M12Mix8Surround 9 + M12Mix8Surround 10 + M12Mix8Surround 11 + M12Mix8Surround 12 + M12Mix8Surround 13 + M12Mix8Surround 14 + M12Mix8Surround 15 + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ M12Mix8Surround0 + + Ret + +EndP Mix12Surround8Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix12Surround8Bit + + Mov AL, [SI+0Eh] + Mov Byte Ptr [CS:M12Surround8BitVolume], AL + + Ret + +EndP PreMix12Surround8Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Mix12Panned8BitOffsetTable Label Word + + IndexCounter = 15 + + M12Mix8PannedOffset Macro Index + DW Offset M12Mix8Panned&Index& + EndM + + REPT 16 + M12Mix8PannedOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix12Panned8Bit + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Push [CS:Mix12Panned8BitOffsetTable+BX] + + M12Mix8PannedNext 0 + + RetN + + M12Mix8Panned 0 + M12Mix8Panned 1 + M12Mix8Panned 2 + M12Mix8Panned 3 + M12Mix8Panned 4 + M12Mix8Panned 5 + M12Mix8Panned 6 + M12Mix8Panned 7 + M12Mix8Panned 8 + M12Mix8Panned 9 + M12Mix8Panned 10 + M12Mix8Panned 11 + M12Mix8Panned 12 + M12Mix8Panned 13 + M12Mix8Panned 14 + M12Mix8Panned 15 + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ M12Mix8Panned0 + + Ret + +EndP Mix12Panned8Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix12Panned8Bit + + Mov AL, [SI+0Eh] + + IndexCounter = 0 + + PreMix12PannedMacro Macro Index + Mov Byte Ptr [CS:M12Mix8PannedVolume&Index&], AL + EndM + + REPT 17 + PreMix12PannedMacro %IndexCounter + IndexCounter = IndexCounter+1 + EndM + + Mov AL, [SI+0Ch] + Sub AL, [SI+0Eh] + Add AL, AL + + IndexCounter = 0 + + PreMix12PannedMacro2 Macro Index + Mov Byte Ptr [CS:M12Mix8PannedRightVolumeOffset&Index&], AL + EndM + + REPT 16 + PreMix12PannedMacro2 %IndexCounter + IndexCounter = IndexCounter+1 + EndM + + Ret + +EndP PreMix12Panned8Bit + +;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ + +Mix12Single16BitOffsetTable Label Word + + IndexCounter = 15 + + M12Mix16SingleOffset Macro Index + DW Offset M12Mix16Single&Index& + EndM + + REPT 16 + M12Mix16SingleOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix12Single16Bit + ; AX = count... + + ; Number of times to loop = (Count-1) / 16 + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Push [CS:Mix12Single16BitOffsetTable+BX] + +M12Single16BitVolume EQU $+3 + Mov EBX, 0 ; Set BH = volume + + RetN + + M12Mix16Single 0 + M12Mix16Single 1 + M12Mix16Single 2 + M12Mix16Single 3 + M12Mix16Single 4 + M12Mix16Single 5 + M12Mix16Single 6 + M12Mix16Single 7 + M12Mix16Single 8 + M12Mix16Single 9 + M12Mix16Single 10 + M12Mix16Single 11 + M12Mix16Single 12 + M12Mix16Single 13 + M12Mix16Single 14 + M12Mix16Single 15 + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ M12Mix16Single0 + + Ret + +EndP Mix12Single16Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix12Left16Bit + + Mov AL, [SI+0Eh] + Mov Byte Ptr [CS:M12Single16BitVolume], AL + Ret + +EndP PreMix12Left16Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix12Right16Bit + + Add MixBufferOffset, MixResolution/8 + Mov AL, [SI+0Ch] + Mov Byte Ptr [CS:M12Single16BitVolume], AL + + Ret + +EndP PreMix12Right16Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Mix12Central16BitOffsetTable Label Word + + IndexCounter = 15 + + M12Mix16CentralOffset Macro Index + DW Offset M12Mix16Central&Index& + EndM + + REPT 16 + M12Mix16CentralOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix12Central16Bit + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Push [CS:Mix12Central16BitOffsetTable+BX] + +M12Central16BitVolume EQU $+3 + Mov EBX, 0 ; Set BH = volume + + + RetN + + M12Mix16Central 0 + M12Mix16Central 1 + M12Mix16Central 2 + M12Mix16Central 3 + M12Mix16Central 4 + M12Mix16Central 5 + M12Mix16Central 6 + M12Mix16Central 7 + M12Mix16Central 8 + M12Mix16Central 9 + M12Mix16Central 10 + M12Mix16Central 11 + M12Mix16Central 12 + M12Mix16Central 13 + M12Mix16Central 14 + M12Mix16Central 15 + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ M12Mix16Central0 + + Ret + +EndP Mix12Central16Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix12Central16Bit + + Mov AL, [SI+0Eh] + Mov Byte Ptr [CS:M12Central16BitVolume], AL + + Ret + +EndP PreMix12Central16Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Mix12Surround16BitOffsetTable Label Word + + IndexCounter = 15 + + M12Mix16SurroundOffset Macro Index + DW Offset M12Mix16Surround&Index& + EndM + + REPT 16 + M12Mix16SurroundOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix12Surround16Bit + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Push [CS:Mix12Surround16BitOffsetTable+BX] + +M12Surround16BitVolume EQU $+3 + Mov EBX, 0 ; Set BH = volume + + + RetN + + M12Mix16Surround 0 + M12Mix16Surround 1 + M12Mix16Surround 2 + M12Mix16Surround 3 + M12Mix16Surround 4 + M12Mix16Surround 5 + M12Mix16Surround 6 + M12Mix16Surround 7 + M12Mix16Surround 8 + M12Mix16Surround 9 + M12Mix16Surround 10 + M12Mix16Surround 11 + M12Mix16Surround 12 + M12Mix16Surround 13 + M12Mix16Surround 14 + M12Mix16Surround 15 + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ M12Mix16Surround0 + + Ret + +EndP Mix12Surround16Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix12Surround16Bit + + Mov AL, [SI+0Eh] + Mov Byte Ptr [CS:M12Surround16BitVolume], AL + + Ret + +EndP PreMix12Surround16Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Mix12Panned16BitOffsetTable Label Word + + IndexCounter = 15 + + M12Mix16PannedOffset Macro Index + DW Offset M12Mix16Panned&Index& + EndM + + REPT 16 + M12Mix16PannedOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix12Panned16Bit + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Push [CS:Mix12Panned16BitOffsetTable+BX] + + M12Mix16PannedNext 0 + + RetN + +Pan12Bit16Loop: + M12Mix16PannedNext 16 + + M12Mix16Panned 0 + M12Mix16Panned 1 + M12Mix16Panned 2 + M12Mix16Panned 3 + M12Mix16Panned 4 + M12Mix16Panned 5 + M12Mix16Panned 6 + M12Mix16Panned 7 + M12Mix16Panned 8 + M12Mix16Panned 9 + M12Mix16Panned 10 + M12Mix16Panned 11 + M12Mix16Panned 12 + M12Mix16Panned 13 + M12Mix16Panned 14 + + M12Mix16Panned15: + Add BX, BX + Add ERROR, DELTAERROR + AdC DI, DELTAOFFSET + Mov AX, [BX] + Sub [SI+EXTRAOFFSET], AX + M12Mix16PannedRightVolumeOffset15 EQU $+3 + Mov AX, [BX+1200h] + Sub [SI+MixResolution/8+EXTRAOFFSET], AX + + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ Pan12Bit16Loop + + Ret + +EndP Mix12Panned16Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix12Panned16Bit + + Mov AL, [SI+0Eh] + + IndexCounter = 0 + + PreMix12PannedMacro Macro Index + Mov Byte Ptr [CS:M12Mix16PannedVolume&Index&], AL + EndM + + REPT 17 + PreMix12PannedMacro %IndexCounter + IndexCounter = IndexCounter+1 + EndM + + Mov AL, [SI+0Ch] + Sub AL, [SI+0Eh] + Add AL, AL + + IndexCounter = 0 + + PreMix12PannedMacro2 Macro Index + Mov Byte Ptr [CS:M12Mix16PannedRightVolumeOffset&Index&], AL + EndM + + REPT 16 + PreMix12PannedMacro2 %IndexCounter + IndexCounter = IndexCounter+1 + EndM + + Ret + +EndP PreMix12Panned16Bit + + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + diff --git a/SoundDrivers/M16.ASM b/SoundDrivers/M16.ASM new file mode 100755 index 0000000..5b88419 --- /dev/null +++ b/SoundDrivers/M16.ASM @@ -0,0 +1,2275 @@ +; +; Terratec Maestro 16/96 +; + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;********************************** + +STEREOENABLED EQU 1 +DMABUFFERLENGTH EQU 4096 +MIXRESOLUTION EQU 32 ; 32 bit mixing for +MIXTABLESIZE EQU 2*256*65 + +PNPVENDORID EQU 2409143Eh + +DMASize DW DMABUFFERLENGTH/2 + +WSSMsg DB "SoundSystem Maestro 16/96", 13 + DB "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, DMA ", 0FDh, "D", 0 + +WSSNoMemoryMsg DB "SoundSystem Maestro 16/96", 13 + DB "Error: Insufficient memory", 0 + +ReinitMsg DB "SoundSystem Maestro 16/96 Codec reinitialised", 0 + +DriverName DB "ITMAES16.DRV", 0 + +Forced DB 0 +Stereo DB 0 +MixVolume DW 0 + +BytesToMix DW 1000 +WSSMixConst DB 0 + +MixSegment DW 0 +DMASegment DW 0 + +MixTransferOffset DW 0 +MixTransferRemaining DW 0 + +CONFIGURATIONOFFSET EQU $+128 +CONFIGSIZE EQU 6 +MixMode DW 0 +MixModeOffset DW 0 +Filter DW 0 + +IMR DW 0 +OldWSSIRQHandler DD 0 + +FilterValue DD 0 +FilterValue2 DD 0 + +MixSpeedTable DW 5513, 41h + DW 6615, 4Fh + DW 8000, 40h + DW 9600, 4Eh + DW 11025, 43h + DW 16000, 42h + DW 18900, 45h + DW 22050, 47h + DW 27429, 44h + DW 32000, 46h + DW 33075, 4Dh + DW 37800, 49h + DW 44100, 4Bh + DW 48000, 4Ch + DW 54860, 48h + DW 64000, 4Ah + +IRQData Label Word + DW 20h, 1111111111111110b ; IRQ 0 + DW 24h, 1111111111111101b ; IRQ 1 + DW 28h, 1111110111111011b ; IRQ 2 + DW 2Ch, 1111111111110111b ; IRQ 3 + DW 30h, 1111111111101111b ; IRQ 4 + DW 34h, 1111111111011111b ; IRQ 5 + DW 38h, 1111111110111111b ; IRQ 6 + DW 3Ch, 1111111101111111b ; IRQ 7 + DW 1C0h, 1111111011111011b ; IRQ 8 + DW 1C4h, 1111110111111011b ; IRQ 9 + DW 1C8h, 1111101111111011b ; IRQ 10 + DW 1CCh, 1111011111111011b ; IRQ 11 + DW 1D0h, 1110111111111011b ; IRQ 12 + DW 1D4h, 1101111111111011b ; IRQ 13 + DW 1D8h, 1011111111111011b ; IRQ 14 + DW 1DCh, 0111111111111011b ; IRQ 15 + +;********************************** +; WSS Registers +;********************************** + +CODEC_INDEX_LIC = 00 +CODEC_INDEX_RIC = 01h +CODEC_INDEX_LX1C = 02h +CODEC_INDEX_RX1C = 03h +CODEC_INDEX_LX2C = 04h +CODEC_INDEX_RX2C = 05h +CODEC_INDEX_LDC = 06h +CODEC_INDEX_RDC = 07h +CODEC_INDEX_CDF = 08h +CODEC_INDEX_INTF = 09h +CODEC_INDEX_PIN = 0Ah +CODEC_INDEX_TEST = 0Bh +CODEC_INDEX_MISC = 0Ch +CODEC_INDEX_DIGMIX = 0Dh +CODEC_INDEX_UPR_COUNT = 0Eh +CODEC_INDEX_LWR_COUNT = 0Fh + +CODEC_MCE = 40h + +LDC_LDM = 80h +LDC_LDA = 3Fh + +RDC_RDM = 80h +RDC_RDA = 3Fh + +CDF_STEREO = 10h + +INTF_PEN = 01h +INTF_CEN = 02h +INTF_SDC = 04h +INTF_ACAL = 08h +INTF_PPIO = 40h +INTF_CPIO = 80h + +PIN_IEN = 2 + +TEST_ORL = 03h +TEST_ORR = 0Ch +TEST_DRS = 10h +TEST_ACI = 20h +TEST_PUR = 40h +TEST_COR = 80h + +;********************************** + +WSS16ScreenList Label + DW 16 + DW Near Ptr IdleFunctionList + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr WSSHeaderLine + + DW Near Ptr DriverText + + DW Near Ptr MixModeText + DW Near Ptr MixModeButton1 ; 6 + DW Near Ptr MixModeButton2 ; + DW Near Ptr MixModeButton3 ; 8 + DW Near Ptr MixModeButton4 ; 9 + + DW Near Ptr FilterText + DW Near Ptr FilterButton1 ; 11 + DW Near Ptr FilterButton2 + DW Near Ptr FilterButton3 + + DW Near Ptr VolumeText + DW Near Ptr VolumeBox1 + + DW Near Ptr MasterVolumeLeft ; 16 + DW Near Ptr MasterVolumeRight ; 17 + + DW 0 + +WSSHeaderLine DW 10 + DB "SoundSystem Maestro 16/96 Codec Driver", 0 + +EmptyObject DW 1 + DB 0, 0 + DB 0 + DB 0 + +DriverText DW 1 + DB 15, 48 + DB 21h + DB "SoundSystem Maestro 16/96 Codec Driver 1.0 for Impulse Tracker", 0 + +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +IdleFunctionList DD 0 + DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +VolumeText DW 1 + DB 2, 14 + DB 20h + DB "Master Volume Left", 13 + DB "Master Volume Right" + DB 0 + +VolumeBox1 DW 0 + DB 21, 13, 31, 16 + DB 25 + +MasterVolumeLeft DW 9 + DB 22, 14 + DW 0, 63 + DW 9, 0 + DW 0FFFFh, 17, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +MasterVolumeRight DW 9 + DB 22, 15 + DW 0, 63 + DW 9, 1 + DW 16, 6, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +MixModeText DW 1 + DB 2, 18 + DB 20h + DB "Mixing Mode, Playback Frequency: ", 0FDh, "DHz", 0 +MixSpeed DW 48000 + +MixModeButton1 DW 2 + DW 17, 7, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment1 DW 0 + DW 0 + DW Offset SetMixMode +DriverSegment2 DW 0 + DB 3, 20, 32, 22, 8 + DB 0 + DB " 16 Bit, Non-Interpolated", 0 + +MixModeButton2 DW 2 + DW 6, 8, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment3 DW 0 + DW 2 + DW Offset SetMixMode +DriverSegment4 DW 0 + DB 3, 23, 32, 25, 8 + DB 0 + DB " 16 Bit, Interpolated", 0 + +MixModeButton3 DW 2 + DW 7, 9, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment5 DW 0 + DW 4 + DW Offset SetMixMode +DriverSegment6 DW 0 + DB 3, 26, 32, 28, 8 + DB 0 + DB " 32 Bit, Non-Interpolated", 0 + +MixModeButton4 DW 2 + DW 8, 11, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment7 DW 0 + DW 6 + DW Offset SetMixMode +DriverSegment8 DW 0 + DB 3, 29, 32, 31, 8 + DB 0 + DB " 32 Bit, Interpolated", 0 + +FilterText DW 1 + DB 2, 33 + DB 20h + DB "Filter mode", 0 + +FilterButton1 DW 2 + DW 9, 12, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment9 DW 0 + DW 0 + DW Offset SetFilter +DriverSegment10 DW 0 + DB 3, 35, 29, 37, 8 + DB 0 + DB " No Filter", 0 + +FilterButton2 DW 2 + DW 11, 13, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment11 DW 0 + DW 1 + DW Offset SetFilter +DriverSegment12 DW 0 + DB 3, 38, 29, 40, 8 + DB 0 + DB " 50% Filter", 0 + +FilterButton3 DW 2 + DW 12, 0FFFFh, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment13 DW 0 + DW 2 + DW Offset SetFilter +DriverSegment14 DW 0 + DB 3, 41, 29, 43, 8 + DB 0 + DB " 75% Filter", 0 + +VolumeTable DB 2 Dup (56) + +; ÄÄ MixingRoutines ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixBufferPos DW 0 + +include dmasirq.inc +include mix.inc +include m12bit.mix +include m12biti.mix +include m32bit.mix +include m32biti.mix + +MixFunctionTables Label + +include m12bit.inc ; contains the tables +include m12biti.inc +include m32bit.inc +include m32biti.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +RelocationTable Label Word + DW Offset DriverSegment1, Offset DriverSegment2 + DW Offset DriverSegment3, Offset DriverSegment4 + DW Offset DriverSegment5, Offset DriverSegment6 + DW Offset DriverSegment7, Offset DriverSegment8 + DW Offset DriverSegment9, Offset DriverSegment10 + DW Offset DriverSegment11, Offset DriverSegment12 + DW Offset DriverSegment13, Offset DriverSegment14 + DW 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixMode Far + + Push CS + Pop ES + Mov DI, Offset MixMode + + Ret + +EndP GetMixMode + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetFilter Far + + Push CS + Pop ES + Mov DI, Offset Filter + + Ret + +EndP GetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetFilter Far + + Mov AX, [SI+22] + Mov CS:FilterValue, 0 + Mov CS:Filter, AX + + Mov AX, 1 + Ret + +EndP SetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WaitCoDec + + Push CX + + Mov CX, 0F000h + +WaitCoDec1: + In AL, DX + Test AL, AL + JNS WaitCoDec2 + Loop WaitCoDec1 + + StC + +WaitCoDec2: + Pop CX + Ret + +EndP WaitCoDec + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WaitAutoCalibration + + Push CX + Mov CX, 0F000h + +WaitAutoCalibration1: + Mov AL, CODEC_INDEX_TEST + Out DX, AL + Inc DX + In AL, DX + Dec DX + Test AL, TEST_ACI + JNZ WaitAutoCalibration2 + Loop WaitAutoCalibration1 + + StC + +WaitAutoCalibration2: + Pop CX + Ret + +EndP WaitAutoCalibration + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixMode Far + + Mov AX, [SI+22] + + ClI + + Mov CS:MixMode, AX + + Mov BX, 180 + Mul BX + Mov CS:MixModeOffset, AX + + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS:RecalculateAllVolumes + + StI + + Mov AX, 1 + Ret + +EndP SetMixMode + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetWSSMixConst ; Work out value.. and nearest + ; mixspeed value. + + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, CmdLineMixSpeed + Mov CX, MixSpeed + Test AX, AX + JZ GetWSSMixConst1 + + Mov CX, 64000 + Cmp AX, CX + JA GetWSSMixConst1 + + Mov CX, 8000 + Cmp AX, CX + JB GetWSSMixConst1 + + Mov CX, AX + +GetWSSMixConst1: ; CX = desired mixspeed + Mov SI, Offset MixSpeedTable + Mov DX, 16 ; 16 different available speeds + + Xor BX, BX + +GetWSSMixConst2: + LodsW + Cmp AX, BX + JB GetWSSMixConst3 + Cmp AX, CX + JA GetWSSMixConst3 + + Mov BX, AX + Mov DH, [SI] + +GetWSSMixConst3: + LodsW ; Add SI, 2 + Dec DL + JNZ GetWSSMixConst2 + + Mov MixSpeed, BX + Mov WSSMixConst, DH + + Pop DS + PopA + Ret + +EndP GetWSSMixConst + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PingWSS ; Check BasePort, DX = BasePort + ; Preserves DX, destroys AX + + Push DX + + Add DX, 6 + + In AL, DX + Xor AL, AL + Out DX, AL + + Dec DX + Dec DX + Call WaitCodec + JC PingWSSFailure + + In AL, DX + Test AL, AL + JS PingWSSFailure + + Mov AL, CODEC_INDEX_MISC + Out DX, AL + Inc DX ; DX = Data port + In AL, DX + Mov AH, AL ; AH = Revision + + Xor AL, AL ; Write 0 revision + Out DX, AL + In AL, DX + And AX, 8F8Fh + Cmp AL, AH + JNE PingWSSFailure + Dec DX ; DX = AD1848 baseport + + Mov AL, CODEC_MCE or CODEC_INDEX_INTF + Out DX, AL + Inc DX + Mov AL, INTF_ACAL or INTF_SDC + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_INTF + Out DX, AL + Inc DX + Mov AL, INTF_ACAL or INTF_SDC + Out DX, AL + Dec DX + + Call WaitAutoCalibration ; Returns carry if error + ; Carry clear if none. + +; JC PingWSSFailure + + Pop DX + Ret + +PingWSSFailure: + Pop DX + + StC + Ret + + +EndP PingWSS + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +PnP_SerialID DD 0 +PnP_VendorID DD 0 +PnP_ReadPort DW 0 +PnP_CSN DB 0 +PnP_CardFound DB 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_Delay + Assume DS:Driver + + Push AX CX + + Mov CX, 180h +PnP_Delay1: + In AL, 21h + Loop PnP_Delay1 + + Pop CX AX + Ret + +EndP PnP_Delay + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_WriteData + + Mov DX, 279h + Out DX, AL + + Mov AL, AH + Mov DH, 0Ah + Out DX, AL + Ret + +EndP PnP_WriteData + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_ReadData + + Mov DX, 279h + Out DX, AL + + Mov DX, PnP_ReadPort + In AL, DX + + Ret + +EndP PnP_ReadData + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_Isolate + + Mov AX, 402h + Call Pnp_WriteData ; Reset CSNs + +PnP_IsolateNextCard: + Mov AX, 0003h + Call PnP_WriteData ; Wake[0] + + Mov AX, PnP_ReadPort + ShL AX, 6 + Xor AL, AL + Call PnP_WriteData ; Set Read Data port. + + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + + Mov AL, 1 ; Serial Isolation + Mov DX, 279h + Out DX, AL + + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + + Mov BL, 6Ah + Mov CX, 64 + Mov DX, PnP_ReadPort + + ClI + +PnP_Isolate1: + ShR PnP_SerialID, 1 + RCR PnP_VendorID, 1 + + Mov BH, BL + ShR BH, 1 + Xor BH, BL + ShR BX, 1 + + In AL, DX + Mov AH, AL + Call PnP_Delay + In AL, DX + Call PnP_Delay + + Cmp AX, 55AAh + JNE PnP_Isolate2 + + Xor BL, 80h + Or PnP_SerialID, 80000000h + +PnP_Isolate2: + Dec CX + JNZ PnP_Isolate1 + + Mov CX, 8 + Xor BH, BH + +PnP_Isolate3: + ShR BH, 1 + + In AL, DX + Mov AH, AL + Call PnP_Delay + In AL, DX + Call PnP_Delay + Cmp AX, 55AAh + JNE PnP_Isolate4 + + Or BH, 80h + +PnP_Isolate4: + Dec CX + JNZ PnP_Isolate3 + + StI + + Cmp BL, BH ; Matching Checksum? + JNE PnP_IsolateFinished + + ; assign CSN + Inc PnP_CSN + + Mov AL, 6 + MOv AH, PnP_CSN + Call PnP_WriteData + + Cmp PnP_VendorID, PNPVENDORID + JNE PnP_IsolateNextCard +; Cmp PnP_SerialID, PNPSERIALID +; JNE PnP_IsolateNextCard + + Mov AL, 3 + Call PnP_WriteData + + Mov AX, 07h ; Configuration device + Call PnP_WriteData + + Mov AL, 62h + Call PnP_ReadData + Mov AH, AL + Mov AL, 63h + Call PnP_ReadData ; AX = address. + + Test AX, AX + JZ PnP_IsolateNextCard + + Cmp BasePort, 0FFFFh + JE PnPBasePortOK + + Cmp BasePort, AX + JNE PnP_IsolateNextCard + +PnPBasePortOK: + Mov BasePort, AX + + Mov AL, 70h + Call PnP_ReadData ; AL[3:0] = IRQ + And AX, 15 + JZ PnP_IsolateNextCard + Mov IRQ, AX + + Mov AL, 74h + Call PnP_ReadData ; AL[2:0] = DMA + And AX, 7 + Cmp AL, 4 + JE PnP_IsolateNextCard + Mov DMA, AX + + Mov Pnp_CardFound, 1 + Jmp PnP_IsolateNextCard + +PnP_IsolateFinished: + Mov AL, PnP_CSN + ShL AL, 1 + Or AL, PnP_CardFound + + Ret + +EndP PnP_Isolate + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far ; returns carry clear if succesful + + Push CS + Pop DS + + Xor AL, AL + Mov DX, 279h + Out DX, AL + Out DX, AL + + Mov AL, 6Ah ; Starting value + Mov CX, 32 + +PnP_InitiationKeyLoop: + Out DX, AL + + Mov AH, AL + ShR AH, 1 + Xor AH, AL + ShR AX, 1 + + Dec CX + JNZ PnP_InitiationKeyLoop + +; Try three ports before concluding no PnP cards: 20Fh, 27Bh, 213h + +PnP_DetectCardPort1: + Mov PnP_ReadPort, 20Fh + Call PnP_Isolate + JZ PnP_DetectCardPort2 + Test AL, 1 + JZ PnP_DetectCardNotFound + Jmp PnP_DetectCardFound + +PnP_DetectCardPort2: + Mov PnP_ReadPort, 27Bh + Call PnP_Isolate + JZ PnP_DetectCardPort3 + Test AL, 1 + JZ PnP_DetectCardNotFound + Jmp PnP_DetectCardFound + +PnP_DetectCardPort3: + Mov PnP_ReadPort, 213h + Call PnP_Isolate + Test AL, 1 + JNZ PnP_DetectCardFound + +PnP_DetectCardNotFound: + StC + Mov AX, 202h + Call PnP_WriteData + Ret + +PnP_DetectCardFound: + ClC + +PnP_DetectEnd: ; Return PnP to wait for key state + Mov AX, 202h + Call PnP_WriteData + + Mov EAX, 'Jeff' + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixModeTable Label Word + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + +Proc MixSamples ; Given DS:SI = info tables, CX = numchannels + + ; 1. Clean buffer + ; + update variables + ; 2. Update parameters + ; 3. Mix func + ; 4. Return + + Push CX + + Mov CX, BytesToMix + Mov ES, MixSegment + Mov DI, MIXTABLESIZE + Xor EAX, EAX + Mov DX, CX + Add CX, CX + + Mov MixTransferOffset, DI ; } Memory write + + Cmp Stereo, 0 + JE MixSamples1 + + Mov DX, CX + +MixSamples1: + Rep StosD ; } Memory write + Mov MixTransferRemaining, DX ; } + + Pop CX + +MixSamples2: + Test Byte Ptr [SI], 1 + JZ MixSamplesEnd2 + Cmp Byte Ptr [SI+36h], 100 + JE MixSamplesEnd2 + + Push CX + Mov CX, [SI] + + Test CH, 2 + JZ MixSamples3 + And Byte Ptr [SI], Not 1 + + Jmp MixSamplesEnd +; Cmp MixMode, 8 ; Is it volume ramping? +; JB MixSamplesEnd + +MixSamples3: + Test CL, 20h ; New freq? + JZ MixSamples5 + + Mov AX, [SI+10h] + Mov DX, [SI+12h] + Mov BX, MixSpeed + Cmp DX, BX + JAE MixSamplesHandleError + + Div BX + ShL EAX, 16 + Xor AX, AX + Div BX + Mov STEPVALUE, EAX + +MixSamples4: + Test CH, 1 + JZ MixSamples5 + + Mov DWord Ptr [SI+1Ch], 0 ; Current Volume = 0 + ; for volume sliding. +MixSamples5: + Test CX, 8440h ; New volume or panning? + JZ MixSamplesMix + + Xor AX, AX + Test CH, 8 ; Muted? + JNZ MixModeCommon + + Mov BX, MixMode + Add BL, Stereo + Add BX, BX + Jmp [CS:MixModeTable+BX] + +Mix0Mode: ; 16-bit mixing, no interpolation +Mix0ModeMono: ; and 16-bit mixing, interpolation + Mov AL, [SI+20h] + ShR AL, 1 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 30 ; Use left only-mixing for mono + Jmp MixModeCommon + +Mix0ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix0ModeSurround + + Mul Byte Ptr [SI+20h] ; Final volume + Add AX, 64 + ShR AX, 7 + Mov [SI+0Ch], AX ; Store into right volume + + Mov AL, 64 + Sub AL, [SI+37h] + Mul Byte Ptr [SI+20h] + Add AX, 64 + ShR AX, 7 + Mov [SI+0Eh], AX ; Left volume + + Mov CH, AL ; CH = left volume + Mov CL, [SI+0Ch] ; CL = right volume + Mov AX, 0 + + Test CX, CX + JZ MixModeCommon + + Mov AL, 30 ; Left only... + Test CL, CL + JZ MixModeCommon + + Mov AL, 60 + Test CH, CH + JZ MixModeCommon + + Mov AL, 90 + Cmp CL, CH + JZ MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix0ModeSurround: + Mov AL, [SI+20h] + ShR AL, 2 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 150 ; Surround + Jmp MixModeCommon + +Mix6ModeMono: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 8 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Test AX, AX + JZ MixModeCommon + Mov AX, 30 + Jmp MixModeCommon + +Mix6ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix6ModeSurround + + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Ch], AX ; Store into right volume + Mov BX, AX + ShL EAX, 16 + + Mov AL, 64 ; Do left volume + Sub AL, [SI+37h] ; AL = 64-FinalPan + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Eh], AX + + Mov ECX, EAX + + ; BX = right volume + ; CX = Left volume + Mov AX, 0 + Test ECX, ECX + JZ MixModeCommon + + Mov AL, 30 + Test BX, BX + JZ MixModeCommon + + Mov AL, 60 + Test CX, CX + JZ MixModeCommon + + Mov AL, 90 + Cmp CX, BX + JE MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix6ModeSurround: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 9 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + JZ MixModeCommon + Mov AX, 150 + Jmp MixModeCommon + +MixModeCommon: ; Requires AX = 30/60/90 etc. depending + ; On mixing mode type. + ; This will add 180 for 16-bit, + ; And sort out loop types. + Mov BL, [SI+0Ah] + Test Byte Ptr [SI+18h], 2 ; 16 bit? + JZ MixModeCommon1 + + Add AX, 180 + +MixModeCommon1: + Cmp BL, 8 + JB MixModeCommon3 ; No loop + JE MixModeCommon2 ; Forwards loop + + Add AX, 10 + +MixModeCommon2: + Add AX, 10 + +MixModeCommon3: + Add AX, Offset MixFunctionTables + Add AX, MixModeOffset + Mov [SI+8], AX ; Offset... + +MixSamplesMix: + Mov BX, [SI+8] ; BX = offset into + Mov EAX, [CS:BX+2] + Mov DWord Ptr PreMixFunction, EAX + Mov EAX, [CS:BX+6] + Mov DWord Ptr MixFunctionSeparateBackwards, EAX + + Mov AX, BytesToMix + Mov MixBlockSize, AX + Mov MixBufferOffset, MIXTABLESIZE + + Mov EAX, CURRENTPOSITION + Mov OLDPOSITION, EAX + + Call Word Ptr [CS:BX] + + And Word Ptr [SI], 0111100010001101b + Jmp MixSamplesEnd + +MixSamplesHandleError: + Mov Word Ptr [SI], 200h + + Test Byte Ptr [SI+3Ah], 80h + JNZ MixSamplesEnd + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Turn off channel + +MixSamplesEnd: + Pop CX + +MixSamplesEnd2: + Add SI, 128 + Dec CX + JNZ MixSamples2 + + Ret + +EndP MixSamples + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WSSIRQHandler + + PushAD + Push DS + Push ES + + ClD + + Mov AX, CS + Mov DS, AX + Assume DS:Driver + + Mov DX, [BasePort] + Add DX, 6 + In AL, DX + Test AL, 1 + JZ WSSAckIRQ2 + + Xor AL, AL + Out DX, AL + +WSSAckIRQ2: + Mov AL, 20h + Cmp IRQ, 8 + JB WSSAckIRQ1 + + Out 0A0h, AL + +WSSAckIRQ1: + Out 20h, AL + +DMAPort1 EQU $+1 + In AL, 1 + Mov BL, AL +DMAPort2 EQU $+1 + In AL, 1 + Mov BH, AL + + Xor AX, AX + + Cmp BX, DMABUFFERLENGTH/2 + JB WSSIRQHandler1 + + Mov AX, DMABUFFERLENGTH/2 + +WSSIRQHandler1: + CLD + + + ; OK... time to get next block + ; Check whether stereo thing is on.. + ; + LES DI, [ActualDMAPtr] + Add DI, AX + + Mov BX, DMASize ; BX = bytes required + ShR BX, 1 + ; BX = samples required + Mov BP, 8 ; Skip for mono + Mov CL, 14 ; Shift for mono + + Cmp Stereo, 0 + JE WSSIRQHandlerMono + + Mov BP, 4 ; Stereo skip value. + Dec CL + +WSSIRQHandlerMono: + Call SaveEMSPageFrame + + Cmp MixTransferRemaining, 0 + JNE WSSIRQHandler4 + Assume DS:Nothing + +WSSIRQHandler3: + Push BX + Push CX + Push BP + Push ES + Push DI + + Call Update + Call MixSamples + + Pop DI + Pop ES + Pop BP + Pop CX + Pop BX + +WSSIRQHandler4: + Mov DS, MixSegment + Mov SI, MixTransferOffset + Mov DX, BX ; DX = samples to transfer + Cmp DX, MixTransferRemaining + JBE WSSIRQHandler5 + + Mov DX, MixTransferRemaining + +WSSIRQHandler5: + Push DX + Cmp CS:Filter, 1 + JB WSSIRQHandler6 + JE WSSIRQHFilter + + Cmp CS:Stereo, 0 + JE WSSIRQ3QFilterMono + +WSSIRQ3QFilterStereo: + Push BX + + Mov EBX, FilterValue + Mov EBP, FilterValue2 + ShR DX, 1 + +WSSIRQ3QFilterStereo1: + Mov EAX, EBX + Mov ECX, EBP + Add EAX, [SI] + Add ECX, [SI+4] + SAR EAX, 1 + SAR ECX, 1 + Add EBX, EAX + Add EBP, ECX + SAR EBX, 1 + SAR EBP, 1 + + Mov EAX, EBX + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSS3QFilterStereoClip1 + Cmp EAX, 7FFFh + JG WSS3QFilterStereoClip2 + +WSSIRQ3QFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSS3QFilterStereoClip3 + Cmp EAX, 7FFFh + JG WSS3QFilterStereoClip4 + +WSSIRQ3QFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ WSSIRQ3QFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp WSSMixTransferEnd + +WSSIRQ3QFilterMono: + Push BX + + Mov EBX, FilterValue + +WSSIRQ3QFilterMono1: + Mov EAX, EBX + Add EAX, [SI] + SAR EAX, 1 + Add EBX, EAX + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL WSS3QFilterMonoClip1 + Cmp EAX, 7FFFh + JG WSS3QFilterMonoClip2 + +WSSIRQ3QFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ WSSIRQ3QFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp WSSMixTransferEnd + +WSSIRQHFilter: + Cmp CS:Stereo, 0 + JE WSSIRQHFilterMono + +WSSIRQHFilterStereo: + Push BX + + Mov EBX, FilterValue + Mov EBP, FilterValue2 + ShR DX, 1 + +WSSIRQHFilterStereo1: + Add EBX, [SI] + Add EBP, [SI+4] + + SAR EBX, 1 + SAR EBP, 1 + + Mov EAX, EBX + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSSHFilterStereoClip1 + Cmp EAX, 7FFFh + JG WSSHFilterStereoClip2 + +WSSIRQHFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSSHFilterStereoClip3 + Cmp EAX, 7FFFh + JG WSSHFilterStereoClip4 + +WSSIRQHFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ WSSIRQHFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp WSSMixTransferEnd + +WSSIRQHFilterMono: + Push BX + + Mov EBX, FilterValue + +WSSIRQHFilterMono1: + Add EBX, [SI] + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL WSSHFilterMonoClip1 + Cmp EAX, 7FFFh + JG WSSHFilterMonoClip2 + +WSSIRQHFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ WSSIRQHFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp WSSMixTransferEnd + +WSSIRQHandler6: + Mov EAX, [SI] + SAR EAX, CL + + Cmp EAX, -8000h + JL WSSIRQHandlerClip1 + Cmp EAX, 7FFFh + JG WSSIRQHandlerClip2 + +WSSIRQHandler7: + StosW ; } Memory write + + Add SI, BP + Dec DX + JNZ WSSIRQHandler6 + +WSSMixTransferEnd: + Pop DX + + Sub MixTransferRemaining, DX ; } Memory write + Sub BX, DX + JNZ WSSIRQHandler3 + + Mov MixTransferOffset, SI ; } Memory write + + Call RestoreEMSPageFrame + + Pop ES + Pop DS + PopAD + IRet + +WSSIRQHandlerClip1: + Mov AX, 8000h + Jmp WSSIRQHandler7 + +WSSIRQHandlerClip2: + Mov AX, 7FFFh + Jmp WSSIRQHandler7 + +WSSHFilterMonoClip1: + Mov AX, 8000h + Jmp WSSIRQHFilterMono2 + +WSSHFilterMonoClip2: + Mov AX, 7FFFh + Jmp WSSIRQHFilterMono2 + +WSSHFilterStereoClip1: + Mov AX, 8000h + Jmp WSSIRQHFilterStereo2 + +WSSHFilterStereoClip2: + Mov AX, 7FFFh + Jmp WSSIRQHFilterStereo2 + +WSSHFilterStereoClip3: + Mov AX, 8000h + Jmp WSSIRQHFilterStereo3 + +WSSHFilterStereoClip4: + Mov AX, 7FFFh + Jmp WSSIRQHFilterStereo3 + +WSS3QFilterMonoClip1: + Mov AX, 8000h + Jmp WSSIRQ3QFilterMono2 + +WSS3QFilterMonoClip2: + Mov AX, 7FFFh + Jmp WSSIRQ3QFilterMono2 + +WSS3QFilterStereoClip1: + Mov AX, 8000h + Jmp WSSIRQ3QFilterStereo2 + +WSS3QFilterStereoClip2: + Mov AX, 7FFFh + Jmp WSSIRQ3QFilterStereo2 + +WSS3QFilterStereoClip3: + Mov AX, 8000h + Jmp WSSIRQ3QFilterStereo3 + +WSS3QFilterStereoClip4: + Mov AX, 7FFFh + Jmp WSSIRQ3QFilterStereo3 + +EndP WSSIRQHandler + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Add DI, Offset IRQData + Mov BX, [CS:DI] + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset WSSIRQHandler + + XChg [ES:BX], EAX + Mov OldWSSIRQHandler, EAX + + Mov AX, IMR + And AX, [DI+2] + + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Pop ES + PopAD + + Ret + +EndP SetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Mov BX, [IRQData+DI] + + Mov EAX, OldWSSIRQHandler + Mov [ES:BX], EAX + + Pop ES + PopAD + + Ret + +EndP ResetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StopWSS + + Mov DX, BasePort + Add DX, 4 + + Mov AL, CODEC_INDEX_INTF + Out DX, AL + Inc DX + In AL, DX + And AL, Not INTF_PEN + Out DX, AL + + Inc DX + In AL, DX + Xor AL, AL + Out DX, AL + + Dec DX + Dec DX + + Mov AL, CODEC_INDEX_PIN + Out DX, AL + Inc DX + Xor AL, AL + Out DX, AL + + Ret + +EndP StopWSS + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StartWSS + + PushA + Push ES + Push DS + + Push CS + Pop DS + Assume DS:Driver + + ; Setup DMA + Mov BX, DMASegment + Xor AX, AX + Mov DX, DMA + Mov DI, DMABUFFERLENGTH + Call SetDMA + + LES DI, ActualDMAPtr + Xor AX, AX + Mov CX, DMABUFFERLENGTH/2 + Rep StosW + + Mov MixBufferPos, 0 + Mov MixTransferRemaining, 0 + + Mov DX, BasePort + Call PingWSS + Add DX, 4 + + Mov AL, CODEC_INDEX_PIN + Out DX, AL + Inc DX + Mov AL, PIN_IEN + Out DX, AL + Dec DX + + Mov AH, WSSMixConst ; Set format/frequency + Cmp Stereo, 0 + JE StartWSS1 + + Or AH, CDF_STEREO + +StartWSS1: + Mov AL, CODEC_MCE or CODEC_INDEX_CDF + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Call WaitCodec + + Mov AL, CODEC_INDEX_CDF + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Call WaitAutoCalibration + + ; Start playback + Mov AL, CODEC_INDEX_LWR_COUNT + Out DX, AL + Inc DX + + Mov AX, DMASize + ShR AX, 1 + + Cmp Stereo, 0 + JE StartWSS2 + + ShR AX, 1 + +StartWSS2: + Dec AX + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_UPR_COUNT + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_INTF + Out DX, AL + Inc DX + In AL, DX + Or AL, INTF_PEN + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_LDC + Out DX, AL + Inc DX + In AL, DX + And AL, Not LDC_LDM + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_RDC + Out DX, AL + Inc DX + In AL, DX + And AL, Not RDC_RDM + Out DX, AL + Dec DX + + Pop DS + Pop ES + PopA + + Ret + +EndP StartWSS + Assume DS:Nothing + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov SI, Offset RelocationTable + +RelocationFix: + LodsW + Test AX, AX + JZ RelocationEnd + Mov BX, AX + Mov [BX], DS + Jmp RelocationFix + + +RelocationEnd: + Call GetEMSPageFrame + Mov EMSPageFrame, AX + + In AL, 0A1h + Mov AH, AL + In AL, 21h + Mov IMR, AX + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + Call GetWSSMixConst + + Mov AX, 2643 + Mul MixSpeed + Add AX, 0FFFFh + AdC DX, 2080 + + Mov BX, (DMABUFFERLENGTH*2)/16 + Add BX, DX + + ; Allocate MixSegment first + Mov AH, 48h + + Int 21h + JNC InitSound1 + +InitSoundNoMemory: + Mov SI, Offset WSSNoMemoryMsg + Ret + +InitSound1: + Mov MixSegment, AX + Add AX, DX + Mov DMASegment, AX + + Call SetIRQ + Call GetTempo + Call SetTempo + + Call UpdateSoundcardVariables + + Mov SI, Offset WSSMsg + + Mov AX, BasePort + Mov BX, IRQ + Mov CX, DMA + + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Call ResetIRQ + Call SetIRQ + + Mov SI, Offset ReInitMsg + Mov BX, 40 + Call SetInfoLine + + Mov AL, Stereo + Call SetStereo + + Pop ES + Pop DS + PopA + + Ret + +EndP ReInitSound + Assume DS:Nothing + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, IMR + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Mov AX, MixSegment + Test AX, AX + JZ UnInitSound1 + + Mov ES, AX + Mov AH, 49h ; Release MixSegment + Int 21h + + Call StopWSS + Call ResetIRQ + +UnInitSound1: + Call GotoHomeDirectory + + ; Now to save config into driver file. + Mov AX, 3D02h ; Read write access + Mov DX, Offset DriverName + Int 21h + JC SetMixMode1 + + Mov BX, AX + + Mov AX, 4200h + Xor CX, CX + Mov DX, Offset CONFIGURATIONOFFSET + Int 21h + JC SetMixMode2 + + Mov AH, 40h + Mov CX, CONFIGSIZE + Mov DX, Offset MixMode + Int 21h + +SetMixMode2: + Mov AH, 3Eh + Int 21h + +SetMixMode1: + Ret + +EndP UnInitSound + Assume DS:Nothing + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + Ret + +EndP Poll + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Push AX + Push BX + Push DX + + Push BX + + Mov AX, MixSpeed + Mov BX, AX + Xor DX, DX + + ShL AX, 1 + RCL DX, 1 ; DX:AX = Mixspeed*2 + + ShR BX, 1 ; BX = Mixspeed/2 + + Add AX, BX + AdC DX, 0 ; DX:AX = Mixspeed*2.5 + + Pop BX ; BX = tempo + Div BX + + Mov BytesToMix, AX + + Pop DX + Pop BX + Pop AX + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + PushA + Push DS + + Mov BX, AX ; BX = MixVolume + Mov CS:MixVolume, BX + + Mov AX, CS:MixSegment + Test AX, AX + JZ SetMixVolume2 + + Mov DS, AX + + Mov CX, MIXTABLESIZE/2 + Mov SI, MIXTABLESIZE-2; Starting point - working backwards + +SetMixVolume1: + Mov AX, CX + + Dec AX ; AH = volume, AL = wave value. + Xor DX, DX + XChg AH, DL ; DL = Volume, AX = wave value + CBW + + IMul DX ; DX:AX = Volume * Wave Value + ; Ranges -8192->8128 + + IMul BX ; DX:AX = Volume * Wave Value * Mixing Volume + ; Ranges -1048576->1040384 + + Add AX, 64 + AdC DX, 0 + + ShRD AX, DX, 7 + Mov [SI], AX + Sub SI, 2 + + Loop SetMixVolume1 + +SetMixVolume2: + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS: RecalculateAllVolumes + + Pop DS + PopA + + Ret + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc RecalculateAllFrequencies + + Call GetChannelTables + +RecalculateAllFrequencies1: + Or Byte Ptr [SI], 32 + + Add SI, 128 + Dec CX + JNZ RecalculateAllFrequencies1 + + Ret + +EndP RecalculateAllFrequencies + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Mov CS:Stereo, AL + Cmp CS:MixSegment, 0 + JE SetStereo1 + + Call StopWSS + Call StartWSS + + Call RecalculateAllFrequencies + +SetStereo1: + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include loadsam.inc + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset WSS16ScreenList + + ClC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far + + Xor AH, AH + Mov AL, [CS:VolumeTable+DI] + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UpdateSoundcardVariables + + Push AX DX + + Push CS + Pop DS + Assume DS:Driver + + Mov DX, BasePort + Add DX, 4 + + Mov AL, CODEC_INDEX_LDC + Out DX, AL + Inc DX + Mov AX, 3F3Fh + Sub AX, [Word Ptr VolumeTable] + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_RDC + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Pop DX AX + Ret + +EndP UpdatesoundcardVariables + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far + + Push DS + Push DX + + Push CS + Pop DS + Assume DS:Driver + + Mov [VolumeTable+DI], AL + Call UpdateSoundcardVariables + + Pop DX + Pop DS + Ret + +EndP SetVariable + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. + +StopAfterPlay DW 0 +DefaultChannels DW 64 + DW 5 Dup (0) + + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/M16.BAT b/SoundDrivers/M16.BAT new file mode 100755 index 0000000..f5023d7 --- /dev/null +++ b/SoundDrivers/M16.BAT @@ -0,0 +1,5 @@ +tasm /m /ut310 m16 +tlink /3 m16 +execom m16 itmaes16.drv +copy itmaes16.drv .. + diff --git a/SoundDrivers/M32.ASM b/SoundDrivers/M32.ASM new file mode 100755 index 0000000..1736ea8 --- /dev/null +++ b/SoundDrivers/M32.ASM @@ -0,0 +1,2271 @@ +; +; Windows Sound System Driver +; + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;********************************** + +STEREOENABLED EQU 1 +DMABUFFERLENGTH EQU 4096 +MIXRESOLUTION EQU 32 ; 32 bit mixing for +MIXTABLESIZE EQU 2*256*65 + +PNPVENDORID EQU 321A630Eh + +DMASize DW DMABUFFERLENGTH/2 + +WSSMsg DB "SoundSystem Maestro 32/96", 13 + DB "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, DMA ", 0FDh, "D", 0 + +WSSNoMemoryMsg DB "SoundSystem Maestro 32/96", 13 + DB "Error: Insufficient memory", 0 + +ReinitMsg DB "SoundSystem Maestro 32/96 Codec reinitialised", 0 + +DriverName DB "ITMAES32.DRV", 0 + +Forced DB 0 +Stereo DB 0 +MixVolume DW 0 + +BytesToMix DW 1000 +WSSMixConst DB 0 + +MixSegment DW 0 +DMASegment DW 0 + +MixTransferOffset DW 0 +MixTransferRemaining DW 0 + +CONFIGURATIONOFFSET EQU $+128 +CONFIGSIZE EQU 6 +MixMode DW 0 +MixModeOffset DW 0 +Filter DW 0 + +IMR DW 0 +OldWSSIRQHandler DD 0 + +FilterValue DD 0 +FilterValue2 DD 0 + +MixSpeedTable DW 5513, 41h + DW 6615, 4Fh + DW 8000, 40h + DW 9600, 4Eh + DW 11025, 43h + DW 16000, 42h + DW 18900, 45h + DW 22050, 47h + DW 27429, 44h + DW 32000, 46h + DW 33075, 4Dh + DW 37800, 49h + DW 44100, 4Bh + DW 48000, 4Ch + +IRQData Label Word + DW 20h, 1111111111111110b ; IRQ 0 + DW 24h, 1111111111111101b ; IRQ 1 + DW 28h, 1111110111111011b ; IRQ 2 + DW 2Ch, 1111111111110111b ; IRQ 3 + DW 30h, 1111111111101111b ; IRQ 4 + DW 34h, 1111111111011111b ; IRQ 5 + DW 38h, 1111111110111111b ; IRQ 6 + DW 3Ch, 1111111101111111b ; IRQ 7 + DW 1C0h, 1111111011111011b ; IRQ 8 + DW 1C4h, 1111110111111011b ; IRQ 9 + DW 1C8h, 1111101111111011b ; IRQ 10 + DW 1CCh, 1111011111111011b ; IRQ 11 + DW 1D0h, 1110111111111011b ; IRQ 12 + DW 1D4h, 1101111111111011b ; IRQ 13 + DW 1D8h, 1011111111111011b ; IRQ 14 + DW 1DCh, 0111111111111011b ; IRQ 15 + +;********************************** +; WSS Registers +;********************************** + +CODEC_INDEX_LIC = 00 +CODEC_INDEX_RIC = 01h +CODEC_INDEX_LX1C = 02h +CODEC_INDEX_RX1C = 03h +CODEC_INDEX_LX2C = 04h +CODEC_INDEX_RX2C = 05h +CODEC_INDEX_LDC = 06h +CODEC_INDEX_RDC = 07h +CODEC_INDEX_CDF = 08h +CODEC_INDEX_INTF = 09h +CODEC_INDEX_PIN = 0Ah +CODEC_INDEX_TEST = 0Bh +CODEC_INDEX_MISC = 0Ch +CODEC_INDEX_DIGMIX = 0Dh +CODEC_INDEX_UPR_COUNT = 0Eh +CODEC_INDEX_LWR_COUNT = 0Fh + +CODEC_MCE = 40h + +LDC_LDM = 80h +LDC_LDA = 3Fh + +RDC_RDM = 80h +RDC_RDA = 3Fh + +CDF_STEREO = 10h + +INTF_PEN = 01h +INTF_CEN = 02h +INTF_SDC = 04h +INTF_ACAL = 08h +INTF_PPIO = 40h +INTF_CPIO = 80h + +PIN_IEN = 2 + +TEST_ORL = 03h +TEST_ORR = 0Ch +TEST_DRS = 10h +TEST_ACI = 20h +TEST_PUR = 40h +TEST_COR = 80h + +;********************************** + +WSS16ScreenList Label + DW 16 + DW Near Ptr IdleFunctionList + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr WSSHeaderLine + + DW Near Ptr DriverText + + DW Near Ptr MixModeText + DW Near Ptr MixModeButton1 ; 6 + DW Near Ptr MixModeButton2 ; + DW Near Ptr MixModeButton3 ; 8 + DW Near Ptr MixModeButton4 ; 9 + + DW Near Ptr FilterText + DW Near Ptr FilterButton1 ; 11 + DW Near Ptr FilterButton2 + DW Near Ptr FilterButton3 + + DW Near Ptr VolumeText + DW Near Ptr VolumeBox1 + + DW Near Ptr MasterVolumeLeft ; 16 + DW Near Ptr MasterVolumeRight ; 17 + + DW 0 + +WSSHeaderLine DW 10 + DB "SoundSystem Maestro 32/96 Codec Driver", 0 + +EmptyObject DW 1 + DB 0, 0 + DB 0 + DB 0 + +DriverText DW 1 + DB 15, 48 + DB 21h + DB "SoundSystem Maestro 32/96 Codec Driver 1.0 for Impulse Tracker", 0 + +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +IdleFunctionList DD 0 + DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +VolumeText DW 1 + DB 2, 14 + DB 20h + DB "Master Volume Left", 13 + DB "Master Volume Right" + DB 0 + +VolumeBox1 DW 0 + DB 21, 13, 31, 16 + DB 25 + +MasterVolumeLeft DW 9 + DB 22, 14 + DW 0, 63 + DW 9, 0 + DW 0FFFFh, 17, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +MasterVolumeRight DW 9 + DB 22, 15 + DW 0, 63 + DW 9, 1 + DW 16, 6, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +MixModeText DW 1 + DB 2, 18 + DB 20h + DB "Mixing Mode, Playback Frequency: ", 0FDh, "DHz", 0 +MixSpeed DW 48000 + +MixModeButton1 DW 2 + DW 17, 7, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment1 DW 0 + DW 0 + DW Offset SetMixMode +DriverSegment2 DW 0 + DB 3, 20, 32, 22, 8 + DB 0 + DB " 16 Bit, Non-Interpolated", 0 + +MixModeButton2 DW 2 + DW 6, 8, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment3 DW 0 + DW 2 + DW Offset SetMixMode +DriverSegment4 DW 0 + DB 3, 23, 32, 25, 8 + DB 0 + DB " 16 Bit, Interpolated", 0 + +MixModeButton3 DW 2 + DW 7, 9, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment5 DW 0 + DW 4 + DW Offset SetMixMode +DriverSegment6 DW 0 + DB 3, 26, 32, 28, 8 + DB 0 + DB " 32 Bit, Non-Interpolated", 0 + +MixModeButton4 DW 2 + DW 8, 11, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment7 DW 0 + DW 6 + DW Offset SetMixMode +DriverSegment8 DW 0 + DB 3, 29, 32, 31, 8 + DB 0 + DB " 32 Bit, Interpolated", 0 + +FilterText DW 1 + DB 2, 33 + DB 20h + DB "Filter mode", 0 + +FilterButton1 DW 2 + DW 9, 12, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment9 DW 0 + DW 0 + DW Offset SetFilter +DriverSegment10 DW 0 + DB 3, 35, 29, 37, 8 + DB 0 + DB " No Filter", 0 + +FilterButton2 DW 2 + DW 11, 13, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment11 DW 0 + DW 1 + DW Offset SetFilter +DriverSegment12 DW 0 + DB 3, 38, 29, 40, 8 + DB 0 + DB " 50% Filter", 0 + +FilterButton3 DW 2 + DW 12, 0FFFFh, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment13 DW 0 + DW 2 + DW Offset SetFilter +DriverSegment14 DW 0 + DB 3, 41, 29, 43, 8 + DB 0 + DB " 75% Filter", 0 + +VolumeTable DB 2 Dup (56) + +; ÄÄ MixingRoutines ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixBufferPos DW 0 + +include dmasirq.inc +include mix.inc +include m12bit.mix +include m12biti.mix +include m32bit.mix +include m32biti.mix + +MixFunctionTables Label + +include m12bit.inc ; contains the tables +include m12biti.inc +include m32bit.inc +include m32biti.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +RelocationTable Label Word + DW Offset DriverSegment1, Offset DriverSegment2 + DW Offset DriverSegment3, Offset DriverSegment4 + DW Offset DriverSegment5, Offset DriverSegment6 + DW Offset DriverSegment7, Offset DriverSegment8 + DW Offset DriverSegment9, Offset DriverSegment10 + DW Offset DriverSegment11, Offset DriverSegment12 + DW Offset DriverSegment13, Offset DriverSegment14 + DW 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixMode Far + + Push CS + Pop ES + Mov DI, Offset MixMode + + Ret + +EndP GetMixMode + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetFilter Far + + Push CS + Pop ES + Mov DI, Offset Filter + + Ret + +EndP GetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetFilter Far + + Mov AX, [SI+22] + Mov CS:FilterValue, 0 + Mov CS:Filter, AX + + Mov AX, 1 + Ret + +EndP SetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WaitCoDec + + Push CX + + Mov CX, 0F000h + +WaitCoDec1: + In AL, DX + Test AL, AL + JNS WaitCoDec2 + Loop WaitCoDec1 + + StC + +WaitCoDec2: + Pop CX + Ret + +EndP WaitCoDec + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WaitAutoCalibration + + Push CX + Mov CX, 0F000h + +WaitAutoCalibration1: + Mov AL, CODEC_INDEX_TEST + Out DX, AL + Inc DX + In AL, DX + Dec DX + Test AL, TEST_ACI + JNZ WaitAutoCalibration2 + Loop WaitAutoCalibration1 + + StC + +WaitAutoCalibration2: + Pop CX + Ret + +EndP WaitAutoCalibration + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixMode Far + + Mov AX, [SI+22] + + ClI + + Mov CS:MixMode, AX + + Mov BX, 180 + Mul BX + Mov CS:MixModeOffset, AX + + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS:RecalculateAllVolumes + + StI + + Mov AX, 1 + Ret + +EndP SetMixMode + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetWSSMixConst ; Work out value.. and nearest + ; mixspeed value. + + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, CmdLineMixSpeed + Mov CX, MixSpeed + Test AX, AX + JZ GetWSSMixConst1 + + Mov CX, 48000 + Cmp AX, CX + JA GetWSSMixConst1 + + Mov CX, 8000 + Cmp AX, CX + JB GetWSSMixConst1 + + Mov CX, AX + +GetWSSMixConst1: ; CX = desired mixspeed + Mov SI, Offset MixSpeedTable + Mov DX, 14 ; 14 different available speeds + + Xor BX, BX + +GetWSSMixConst2: + LodsW + Cmp AX, BX + JB GetWSSMixConst3 + Cmp AX, CX + JA GetWSSMixConst3 + + Mov BX, AX + Mov DH, [SI] + +GetWSSMixConst3: + LodsW ; Add SI, 2 + Dec DL + JNZ GetWSSMixConst2 + + Mov MixSpeed, BX + Mov WSSMixConst, DH + + Pop DS + PopA + Ret + +EndP GetWSSMixConst + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PingWSS ; Check BasePort, DX = BasePort + ; Preserves DX, destroys AX + + Push DX + + Inc DX + Inc DX + + In AL, DX + Xor AL, AL + Out DX, AL + + Dec DX + Dec DX + Call WaitCodec + JC PingWSSFailure + + In AL, DX + Test AL, AL + JS PingWSSFailure + + Mov AL, CODEC_INDEX_MISC + Out DX, AL + Inc DX ; DX = Data port + In AL, DX + Mov AH, AL ; AH = Revision + + Xor AL, AL ; Write 0 revision + Out DX, AL + In AL, DX + And AX, 8F8Fh + Cmp AL, AH + JNE PingWSSFailure + Dec DX ; DX = AD1848 baseport + + Mov AL, CODEC_MCE or CODEC_INDEX_INTF + Out DX, AL + Inc DX + Mov AL, INTF_ACAL or INTF_SDC + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_INTF + Out DX, AL + Inc DX + Mov AL, INTF_ACAL or INTF_SDC + Out DX, AL + Dec DX + + Call WaitAutoCalibration ; Returns carry if error + ; Carry clear if none. + +; JC PingWSSFailure + + Pop DX + Ret + +PingWSSFailure: + Pop DX + + StC + Ret + + +EndP PingWSS + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +PnP_SerialID DD 0 +PnP_VendorID DD 0 +PnP_ReadPort DW 0 +PnP_CSN DB 0 +PnP_CardFound DB 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_Delay + Assume DS:Driver + + Push AX CX + + Mov CX, 180h +PnP_Delay1: + In AL, 21h + Loop PnP_Delay1 + + Pop CX AX + Ret + +EndP PnP_Delay + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_WriteData + + Mov DX, 279h + Out DX, AL + + Mov AL, AH + Mov DH, 0Ah + Out DX, AL + Ret + +EndP PnP_WriteData + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_ReadData + + Mov DX, 279h + Out DX, AL + + Mov DX, PnP_ReadPort + In AL, DX + + Ret + +EndP PnP_ReadData + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_Isolate + + Mov AX, 402h + Call Pnp_WriteData ; Reset CSNs + +PnP_IsolateNextCard: + Mov AX, 0003h + Call PnP_WriteData ; Wake[0] + + Mov AX, PnP_ReadPort + ShL AX, 6 + Xor AL, AL + Call PnP_WriteData ; Set Read Data port. + + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + + Mov AL, 1 ; Serial Isolation + Mov DX, 279h + Out DX, AL + + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + + Mov BL, 6Ah + Mov CX, 64 + Mov DX, PnP_ReadPort + + ClI + +PnP_Isolate1: + ShR PnP_SerialID, 1 + RCR PnP_VendorID, 1 + + Mov BH, BL + ShR BH, 1 + Xor BH, BL + ShR BX, 1 + + In AL, DX + Mov AH, AL + Call PnP_Delay + In AL, DX + Call PnP_Delay + + Cmp AX, 55AAh + JNE PnP_Isolate2 + + Xor BL, 80h + Or PnP_SerialID, 80000000h + +PnP_Isolate2: + Dec CX + JNZ PnP_Isolate1 + + Mov CX, 8 + Xor BH, BH + +PnP_Isolate3: + ShR BH, 1 + + In AL, DX + Mov AH, AL + Call PnP_Delay + In AL, DX + Call PnP_Delay + Cmp AX, 55AAh + JNE PnP_Isolate4 + + Or BH, 80h + +PnP_Isolate4: + Dec CX + JNZ PnP_Isolate3 + + StI + + Cmp BL, BH ; Matching Checksum? + JNE PnP_IsolateFinished + + ; assign CSN + Inc PnP_CSN + + Mov AL, 6 + MOv AH, PnP_CSN + Call PnP_WriteData + + Cmp PnP_VendorID, PNPVENDORID + JNE PnP_IsolateNextCard +; Cmp PnP_SerialID, PNPSERIALID +; JNE PnP_IsolateNextCard + + Mov AL, 3 + Call PnP_WriteData + + Mov AX, 07h ; Configuration device + Call PnP_WriteData + + Mov AL, 60h + Call PnP_ReadData + Mov AH, AL + Mov AL, 61h + Call PnP_ReadData ; AX = address. + + Test AX, AX + JZ PnP_IsolateNextCard + + Cmp BasePort, 0FFFFh + JE PnPBasePortOK + + Cmp BasePort, AX + JNE PnP_IsolateNextCard + +PnPBasePortOK: + Mov BasePort, AX + + Mov AL, 70h + Call PnP_ReadData ; AL[3:0] = IRQ + And AX, 15 + JZ PnP_IsolateNextCard + Mov IRQ, AX + + Mov AL, 74h + Call PnP_ReadData ; AL[2:0] = DMA + And AX, 7 + Cmp AL, 4 + JE PnP_IsolateNextCard + Mov DMA, AX + + Mov Pnp_CardFound, 1 + Jmp PnP_IsolateNextCard + +PnP_IsolateFinished: + Mov AL, PnP_CSN + ShL AL, 1 + Or AL, PnP_CardFound + + Ret + +EndP PnP_Isolate + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far ; returns carry clear if succesful + + Push CS + Pop DS + + Xor AL, AL + Mov DX, 279h + Out DX, AL + Out DX, AL + + Mov AL, 6Ah ; Starting value + Mov CX, 32 + +PnP_InitiationKeyLoop: + Out DX, AL + + Mov AH, AL + ShR AH, 1 + Xor AH, AL + ShR AX, 1 + + Dec CX + JNZ PnP_InitiationKeyLoop + +; Try three ports before concluding no PnP cards: 20Fh, 27Bh, 213h + +PnP_DetectCardPort1: + Mov PnP_ReadPort, 20Fh + Call PnP_Isolate + JZ PnP_DetectCardPort2 + Test AL, 1 + JZ PnP_DetectCardNotFound + Jmp PnP_DetectCardFound + +PnP_DetectCardPort2: + Mov PnP_ReadPort, 27Bh + Call PnP_Isolate + JZ PnP_DetectCardPort3 + Test AL, 1 + JZ PnP_DetectCardNotFound + Jmp PnP_DetectCardFound + +PnP_DetectCardPort3: + Mov PnP_ReadPort, 213h + Call PnP_Isolate + Test AL, 1 + JNZ PnP_DetectCardFound + +PnP_DetectCardNotFound: + StC + Mov AX, 202h + Call PnP_WriteData + Ret + +PnP_DetectCardFound: + ClC + +PnP_DetectEnd: ; Return PnP to wait for key state + Mov AX, 202h + Call PnP_WriteData + + Mov EAX, 'Jeff' + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixModeTable Label Word + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + +Proc MixSamples ; Given DS:SI = info tables, CX = numchannels + + ; 1. Clean buffer + ; + update variables + ; 2. Update parameters + ; 3. Mix func + ; 4. Return + + Push CX + + Mov CX, BytesToMix + Mov ES, MixSegment + Mov DI, MIXTABLESIZE + Xor EAX, EAX + Mov DX, CX + Add CX, CX + + Mov MixTransferOffset, DI ; } Memory write + + Cmp Stereo, 0 + JE MixSamples1 + + Mov DX, CX + +MixSamples1: + Rep StosD ; } Memory write + Mov MixTransferRemaining, DX ; } + + Pop CX + +MixSamples2: + Test Byte Ptr [SI], 1 + JZ MixSamplesEnd2 + Cmp Byte Ptr [SI+36h], 100 + JE MixSamplesEnd2 + + Push CX + Mov CX, [SI] + + Test CH, 2 + JZ MixSamples3 + And Byte Ptr [SI], Not 1 + + Jmp MixSamplesEnd +; Cmp MixMode, 8 ; Is it volume ramping? +; JB MixSamplesEnd + +MixSamples3: + Test CL, 20h ; New freq? + JZ MixSamples5 + + Mov AX, [SI+10h] + Mov DX, [SI+12h] + Mov BX, MixSpeed + Cmp DX, BX + JAE MixSamplesHandleError + + Div BX + ShL EAX, 16 + Xor AX, AX + Div BX + Mov STEPVALUE, EAX + +MixSamples4: + Test CH, 1 + JZ MixSamples5 + + Mov DWord Ptr [SI+1Ch], 0 ; Current Volume = 0 + ; for volume sliding. +MixSamples5: + Test CX, 8440h ; New volume or panning? + JZ MixSamplesMix + + Xor AX, AX + Test CH, 8 ; Muted? + JNZ MixModeCommon + + Mov BX, MixMode + Add BL, Stereo + Add BX, BX + Jmp [CS:MixModeTable+BX] + +Mix0Mode: ; 16-bit mixing, no interpolation +Mix0ModeMono: ; and 16-bit mixing, interpolation + Mov AL, [SI+20h] + ShR AL, 1 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 30 ; Use left only-mixing for mono + Jmp MixModeCommon + +Mix0ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix0ModeSurround + + Mul Byte Ptr [SI+20h] ; Final volume + Add AX, 64 + ShR AX, 7 + Mov [SI+0Ch], AX ; Store into right volume + + Mov AL, 64 + Sub AL, [SI+37h] + Mul Byte Ptr [SI+20h] + Add AX, 64 + ShR AX, 7 + Mov [SI+0Eh], AX ; Left volume + + Mov CH, AL ; CH = left volume + Mov CL, [SI+0Ch] ; CL = right volume + Mov AX, 0 + + Test CX, CX + JZ MixModeCommon + + Mov AL, 30 ; Left only... + Test CL, CL + JZ MixModeCommon + + Mov AL, 60 + Test CH, CH + JZ MixModeCommon + + Mov AL, 90 + Cmp CL, CH + JZ MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix0ModeSurround: + Mov AL, [SI+20h] + ShR AL, 2 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 150 ; Surround + Jmp MixModeCommon + +Mix6ModeMono: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 8 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Test AX, AX + JZ MixModeCommon + Mov AX, 30 + Jmp MixModeCommon + +Mix6ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix6ModeSurround + + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Ch], AX ; Store into right volume + Mov BX, AX + ShL EAX, 16 + + Mov AL, 64 ; Do left volume + Sub AL, [SI+37h] ; AL = 64-FinalPan + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Eh], AX + + Mov ECX, EAX + + ; BX = right volume + ; CX = Left volume + Mov AX, 0 + Test ECX, ECX + JZ MixModeCommon + + Mov AL, 30 + Test BX, BX + JZ MixModeCommon + + Mov AL, 60 + Test CX, CX + JZ MixModeCommon + + Mov AL, 90 + Cmp CX, BX + JE MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix6ModeSurround: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 9 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + JZ MixModeCommon + Mov AX, 150 + Jmp MixModeCommon + +MixModeCommon: ; Requires AX = 30/60/90 etc. depending + ; On mixing mode type. + ; This will add 180 for 16-bit, + ; And sort out loop types. + Mov BL, [SI+0Ah] + Test Byte Ptr [SI+18h], 2 ; 16 bit? + JZ MixModeCommon1 + + Add AX, 180 + +MixModeCommon1: + Cmp BL, 8 + JB MixModeCommon3 ; No loop + JE MixModeCommon2 ; Forwards loop + + Add AX, 10 + +MixModeCommon2: + Add AX, 10 + +MixModeCommon3: + Add AX, Offset MixFunctionTables + Add AX, MixModeOffset + Mov [SI+8], AX ; Offset... + +MixSamplesMix: + Mov BX, [SI+8] ; BX = offset into + Mov EAX, [CS:BX+2] + Mov DWord Ptr PreMixFunction, EAX + Mov EAX, [CS:BX+6] + Mov DWord Ptr MixFunctionSeparateBackwards, EAX + + Mov AX, BytesToMix + Mov MixBlockSize, AX + Mov MixBufferOffset, MIXTABLESIZE + + Mov EAX, CURRENTPOSITION + Mov OLDPOSITION, EAX + + Call Word Ptr [CS:BX] + + And Word Ptr [SI], 0111100010001101b + Jmp MixSamplesEnd + +MixSamplesHandleError: + Mov Word Ptr [SI], 200h + + Test Byte Ptr [SI+3Ah], 80h + JNZ MixSamplesEnd + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Turn off channel + +MixSamplesEnd: + Pop CX + +MixSamplesEnd2: + Add SI, 128 + Dec CX + JNZ MixSamples2 + + Ret + +EndP MixSamples + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WSSIRQHandler + + PushAD + Push DS + Push ES + + ClD + + Mov AX, CS + Mov DS, AX + Assume DS:Driver + + Mov DX, [BasePort] + Add DX, 2 + In AL, DX + Test AL, 1 + JZ WSSAckIRQ2 + + Xor AL, AL + Out DX, AL + +WSSAckIRQ2: + Mov AL, 20h + Cmp IRQ, 8 + JB WSSAckIRQ1 + + Out 0A0h, AL + +WSSAckIRQ1: + Out 20h, AL + +DMAPort1 EQU $+1 + In AL, 1 + Mov BL, AL +DMAPort2 EQU $+1 + In AL, 1 + Mov BH, AL + + Xor AX, AX + + Cmp BX, DMABUFFERLENGTH/2 + JB WSSIRQHandler1 + + Mov AX, DMABUFFERLENGTH/2 + +WSSIRQHandler1: + CLD + + + ; OK... time to get next block + ; Check whether stereo thing is on.. + ; + LES DI, [ActualDMAPtr] + Add DI, AX + + Mov BX, DMASize ; BX = bytes required + ShR BX, 1 + ; BX = samples required + Mov BP, 8 ; Skip for mono + Mov CL, 14 ; Shift for mono + + Cmp Stereo, 0 + JE WSSIRQHandlerMono + + Mov BP, 4 ; Stereo skip value. + Dec CL + +WSSIRQHandlerMono: + Call SaveEMSPageFrame + + Cmp MixTransferRemaining, 0 + JNE WSSIRQHandler4 + Assume DS:Nothing + +WSSIRQHandler3: + Push BX + Push CX + Push BP + Push ES + Push DI + + Call Update + Call MixSamples + + Pop DI + Pop ES + Pop BP + Pop CX + Pop BX + +WSSIRQHandler4: + Mov DS, MixSegment + Mov SI, MixTransferOffset + Mov DX, BX ; DX = samples to transfer + Cmp DX, MixTransferRemaining + JBE WSSIRQHandler5 + + Mov DX, MixTransferRemaining + +WSSIRQHandler5: + Push DX + Cmp CS:Filter, 1 + JB WSSIRQHandler6 + JE WSSIRQHFilter + + Cmp CS:Stereo, 0 + JE WSSIRQ3QFilterMono + +WSSIRQ3QFilterStereo: + Push BX + + Mov EBX, FilterValue + Mov EBP, FilterValue2 + ShR DX, 1 + +WSSIRQ3QFilterStereo1: + Mov EAX, EBX + Mov ECX, EBP + Add EAX, [SI] + Add ECX, [SI+4] + SAR EAX, 1 + SAR ECX, 1 + Add EBX, EAX + Add EBP, ECX + SAR EBX, 1 + SAR EBP, 1 + + Mov EAX, EBX + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSS3QFilterStereoClip1 + Cmp EAX, 7FFFh + JG WSS3QFilterStereoClip2 + +WSSIRQ3QFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSS3QFilterStereoClip3 + Cmp EAX, 7FFFh + JG WSS3QFilterStereoClip4 + +WSSIRQ3QFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ WSSIRQ3QFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp WSSMixTransferEnd + +WSSIRQ3QFilterMono: + Push BX + + Mov EBX, FilterValue + +WSSIRQ3QFilterMono1: + Mov EAX, EBX + Add EAX, [SI] + SAR EAX, 1 + Add EBX, EAX + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL WSS3QFilterMonoClip1 + Cmp EAX, 7FFFh + JG WSS3QFilterMonoClip2 + +WSSIRQ3QFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ WSSIRQ3QFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp WSSMixTransferEnd + +WSSIRQHFilter: + Cmp CS:Stereo, 0 + JE WSSIRQHFilterMono + +WSSIRQHFilterStereo: + Push BX + + Mov EBX, FilterValue + Mov EBP, FilterValue2 + ShR DX, 1 + +WSSIRQHFilterStereo1: + Add EBX, [SI] + Add EBP, [SI+4] + + SAR EBX, 1 + SAR EBP, 1 + + Mov EAX, EBX + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSSHFilterStereoClip1 + Cmp EAX, 7FFFh + JG WSSHFilterStereoClip2 + +WSSIRQHFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSSHFilterStereoClip3 + Cmp EAX, 7FFFh + JG WSSHFilterStereoClip4 + +WSSIRQHFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ WSSIRQHFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp WSSMixTransferEnd + +WSSIRQHFilterMono: + Push BX + + Mov EBX, FilterValue + +WSSIRQHFilterMono1: + Add EBX, [SI] + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL WSSHFilterMonoClip1 + Cmp EAX, 7FFFh + JG WSSHFilterMonoClip2 + +WSSIRQHFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ WSSIRQHFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp WSSMixTransferEnd + +WSSIRQHandler6: + Mov EAX, [SI] + SAR EAX, CL + + Cmp EAX, -8000h + JL WSSIRQHandlerClip1 + Cmp EAX, 7FFFh + JG WSSIRQHandlerClip2 + +WSSIRQHandler7: + StosW ; } Memory write + + Add SI, BP + Dec DX + JNZ WSSIRQHandler6 + +WSSMixTransferEnd: + Pop DX + + Sub MixTransferRemaining, DX ; } Memory write + Sub BX, DX + JNZ WSSIRQHandler3 + + Mov MixTransferOffset, SI ; } Memory write + + Call RestoreEMSPageFrame + + Pop ES + Pop DS + PopAD + IRet + +WSSIRQHandlerClip1: + Mov AX, 8000h + Jmp WSSIRQHandler7 + +WSSIRQHandlerClip2: + Mov AX, 7FFFh + Jmp WSSIRQHandler7 + +WSSHFilterMonoClip1: + Mov AX, 8000h + Jmp WSSIRQHFilterMono2 + +WSSHFilterMonoClip2: + Mov AX, 7FFFh + Jmp WSSIRQHFilterMono2 + +WSSHFilterStereoClip1: + Mov AX, 8000h + Jmp WSSIRQHFilterStereo2 + +WSSHFilterStereoClip2: + Mov AX, 7FFFh + Jmp WSSIRQHFilterStereo2 + +WSSHFilterStereoClip3: + Mov AX, 8000h + Jmp WSSIRQHFilterStereo3 + +WSSHFilterStereoClip4: + Mov AX, 7FFFh + Jmp WSSIRQHFilterStereo3 + +WSS3QFilterMonoClip1: + Mov AX, 8000h + Jmp WSSIRQ3QFilterMono2 + +WSS3QFilterMonoClip2: + Mov AX, 7FFFh + Jmp WSSIRQ3QFilterMono2 + +WSS3QFilterStereoClip1: + Mov AX, 8000h + Jmp WSSIRQ3QFilterStereo2 + +WSS3QFilterStereoClip2: + Mov AX, 7FFFh + Jmp WSSIRQ3QFilterStereo2 + +WSS3QFilterStereoClip3: + Mov AX, 8000h + Jmp WSSIRQ3QFilterStereo3 + +WSS3QFilterStereoClip4: + Mov AX, 7FFFh + Jmp WSSIRQ3QFilterStereo3 + +EndP WSSIRQHandler + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Add DI, Offset IRQData + Mov BX, [CS:DI] + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset WSSIRQHandler + + XChg [ES:BX], EAX + Mov OldWSSIRQHandler, EAX + + Mov AX, IMR + And AX, [DI+2] + + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Pop ES + PopAD + + Ret + +EndP SetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Mov BX, [IRQData+DI] + + Mov EAX, OldWSSIRQHandler + Mov [ES:BX], EAX + + Pop ES + PopAD + + Ret + +EndP ResetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StopWSS + + Mov DX, BasePort + + Mov AL, CODEC_INDEX_INTF + Out DX, AL + Inc DX + In AL, DX + And AL, Not INTF_PEN + Out DX, AL + + Inc DX + In AL, DX + Xor AL, AL + Out DX, AL + + Dec DX + Dec DX + + Mov AL, CODEC_INDEX_PIN + Out DX, AL + Inc DX + Xor AL, AL + Out DX, AL + + Ret + +EndP StopWSS + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StartWSS + + PushA + Push ES + Push DS + + Push CS + Pop DS + Assume DS:Driver + + ; Setup DMA + Mov BX, DMASegment + Xor AX, AX + Mov DX, DMA + Mov DI, DMABUFFERLENGTH + Call SetDMA + + LES DI, ActualDMAPtr + Xor AX, AX + Mov CX, DMABUFFERLENGTH/2 + Rep StosW + + Mov MixBufferPos, 0 + Mov MixTransferRemaining, 0 + + Mov DX, BasePort + Call PingWSS + + Mov AL, CODEC_INDEX_PIN + Out DX, AL + Inc DX + Mov AL, PIN_IEN + Out DX, AL + Dec DX + + Mov AH, WSSMixConst ; Set format/frequency + Cmp Stereo, 0 + JE StartWSS1 + + Or AH, CDF_STEREO + +StartWSS1: + Mov AL, CODEC_MCE or CODEC_INDEX_CDF + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Call WaitCodec + + Mov AL, CODEC_INDEX_CDF + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Call WaitAutoCalibration + + ; Start playback + Mov AL, CODEC_INDEX_LWR_COUNT + Out DX, AL + Inc DX + + Mov AX, DMASize + ShR AX, 1 + + Cmp Stereo, 0 + JE StartWSS2 + + ShR AX, 1 + +StartWSS2: + Dec AX + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_UPR_COUNT + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_INTF + Out DX, AL + Inc DX + In AL, DX + Or AL, INTF_PEN + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_LDC + Out DX, AL + Inc DX + In AL, DX + And AL, Not LDC_LDM + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_RDC + Out DX, AL + Inc DX + In AL, DX + And AL, Not RDC_RDM + Out DX, AL + Dec DX + + Pop DS + Pop ES + PopA + + Ret + +EndP StartWSS + Assume DS:Nothing + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov SI, Offset RelocationTable + +RelocationFix: + LodsW + Test AX, AX + JZ RelocationEnd + Mov BX, AX + Mov [BX], DS + Jmp RelocationFix + + +RelocationEnd: + Call GetEMSPageFrame + Mov EMSPageFrame, AX + + In AL, 0A1h + Mov AH, AL + In AL, 21h + Mov IMR, AX + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + Call GetWSSMixConst + + Mov AX, 2643 + Mul MixSpeed + Add AX, 0FFFFh + AdC DX, 2080 + + Mov BX, (DMABUFFERLENGTH*2)/16 + Add BX, DX + + ; Allocate MixSegment first + Mov AH, 48h + + Int 21h + JNC InitSound1 + +InitSoundNoMemory: + Mov SI, Offset WSSNoMemoryMsg + Ret + +InitSound1: + Mov MixSegment, AX + Add AX, DX + Mov DMASegment, AX + + Call SetIRQ + Call GetTempo + Call SetTempo + + Call UpdateSoundcardVariables + + Mov SI, Offset WSSMsg + + Mov AX, BasePort + Mov BX, IRQ + Mov CX, DMA + + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Call ResetIRQ + Call SetIRQ + + Mov SI, Offset ReInitMsg + Mov BX, 40 + Call SetInfoLine + + Mov AL, Stereo + Call SetStereo + + Pop ES + Pop DS + PopA + + Ret + +EndP ReInitSound + Assume DS:Nothing + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, IMR + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Mov AX, MixSegment + Test AX, AX + JZ UnInitSound1 + + Mov ES, AX + Mov AH, 49h ; Release MixSegment + Int 21h + + Call StopWSS + Call ResetIRQ + +UnInitSound1: + Call GotoHomeDirectory + + ; Now to save config into driver file. + Mov AX, 3D02h ; Read write access + Mov DX, Offset DriverName + Int 21h + JC SetMixMode1 + + Mov BX, AX + + Mov AX, 4200h + Xor CX, CX + Mov DX, Offset CONFIGURATIONOFFSET + Int 21h + JC SetMixMode2 + + Mov AH, 40h + Mov CX, CONFIGSIZE + Mov DX, Offset MixMode + Int 21h + +SetMixMode2: + Mov AH, 3Eh + Int 21h + +SetMixMode1: + Ret + +EndP UnInitSound + Assume DS:Nothing + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + Ret + +EndP Poll + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Push AX + Push BX + Push DX + + Push BX + + Mov AX, MixSpeed + Mov BX, AX + Xor DX, DX + + ShL AX, 1 + RCL DX, 1 ; DX:AX = Mixspeed*2 + + ShR BX, 1 ; BX = Mixspeed/2 + + Add AX, BX + AdC DX, 0 ; DX:AX = Mixspeed*2.5 + + Pop BX ; BX = tempo + Div BX + + Mov BytesToMix, AX + + Pop DX + Pop BX + Pop AX + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + PushA + Push DS + + Mov BX, AX ; BX = MixVolume + Mov CS:MixVolume, BX + + Mov AX, CS:MixSegment + Test AX, AX + JZ SetMixVolume2 + + Mov DS, AX + + Mov CX, MIXTABLESIZE/2 + Mov SI, MIXTABLESIZE-2; Starting point - working backwards + +SetMixVolume1: + Mov AX, CX + + Dec AX ; AH = volume, AL = wave value. + Xor DX, DX + XChg AH, DL ; DL = Volume, AX = wave value + CBW + + IMul DX ; DX:AX = Volume * Wave Value + ; Ranges -8192->8128 + + IMul BX ; DX:AX = Volume * Wave Value * Mixing Volume + ; Ranges -1048576->1040384 + + Add AX, 64 + AdC DX, 0 + + ShRD AX, DX, 7 + Mov [SI], AX + Sub SI, 2 + + Loop SetMixVolume1 + +SetMixVolume2: + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS: RecalculateAllVolumes + + Pop DS + PopA + + Ret + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc RecalculateAllFrequencies + + Call GetChannelTables + +RecalculateAllFrequencies1: + Or Byte Ptr [SI], 32 + + Add SI, 128 + Dec CX + JNZ RecalculateAllFrequencies1 + + Ret + +EndP RecalculateAllFrequencies + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Mov CS:Stereo, AL + Cmp CS:MixSegment, 0 + JE SetStereo1 + + Call StopWSS + Call StartWSS + + Call RecalculateAllFrequencies + +SetStereo1: + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include loadsam.inc + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset WSS16ScreenList + + ClC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far + + Xor AH, AH + Mov AL, [CS:VolumeTable+DI] + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UpdateSoundcardVariables + + Push AX DX + + Push CS + Pop DS + Assume DS:Driver + + Mov DX, BasePort + + Mov AL, CODEC_INDEX_LDC + Out DX, AL + Inc DX + Mov AX, 3F3Fh + Sub AX, [Word Ptr VolumeTable] + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_RDC + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Pop DX AX + Ret + +EndP UpdatesoundcardVariables + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far + + Push DS + Push DX + + Push CS + Pop DS + Assume DS:Driver + + Mov [VolumeTable+DI], AL + Call UpdateSoundcardVariables + + Pop DX + Pop DS + Ret + +EndP SetVariable + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. + +StopAfterPlay DW 0 +DefaultChannels DW 64 + DW 5 Dup (0) + + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/M32.BAT b/SoundDrivers/M32.BAT new file mode 100755 index 0000000..328ebb1 --- /dev/null +++ b/SoundDrivers/M32.BAT @@ -0,0 +1,5 @@ +tasm /m /ut310 m32 +tlink /3 m32 +execom m32 itmaes32.drv +copy itmaes32.drv .. + diff --git a/SoundDrivers/M32BIT.INC b/SoundDrivers/M32BIT.INC new file mode 100755 index 0000000..47bebd5 --- /dev/null +++ b/SoundDrivers/M32BIT.INC @@ -0,0 +1,49 @@ + + DW Offset UpdateNoLoop, 0, 0, 0, 0 ; Update only + DW Offset UpdateForwardsLoop, 0, 0, 0, 0 + DW Offset UpdatePingPongLoop, 0, 0, 0, 0 + ; Left only + DW Offset MixNoLoop, PreMix32Left8Bit, MFS8Bit, MBS8Bit, Mix32Single8Bit + DW Offset MixForwardsLoop, PreMix32Left8Bit, MFS8Bit, MBS8Bit, Mix32Single8Bit + DW Offset MixPingPongLoop, PreMix32Left8Bit, MFS8Bit, MBS8Bit, Mix32Single8Bit + ; Right only + DW Offset MixNoLoop, PreMix32Right8Bit, MFS8Bit, MBS8Bit, Mix32Single8Bit + DW Offset MixForwardsLoop, PreMix32Right8Bit, MFS8Bit, MBS8Bit, Mix32Single8Bit + DW Offset MixPingPongLoop, PreMix32Right8Bit, MFS8Bit, MBS8Bit, Mix32Single8Bit + ; Central + DW Offset MixNoLoop, PreMix32Central8Bit, MFS8Bit, MBS8Bit, Mix32Central8Bit + DW Offset MixForwardsLoop, PreMix32Central8Bit, MFS8Bit, MBS8Bit, Mix32Central8Bit + DW Offset MixPingPongLoop, PreMix32Central8Bit, MFS8Bit, MBS8Bit, Mix32Central8Bit + ; Stereo + DW Offset MixNoLoop, PreMix32Panned8Bit, MFS8Bit, MBS8Bit, Mix32Panned8Bit + DW Offset MixForwardsLoop, PreMix32Panned8Bit, MFS8Bit, MBS8Bit, Mix32Panned8Bit + DW Offset MixPingPongLoop, PreMix32Panned8Bit, MFS8Bit, MBS8Bit, Mix32Panned8Bit + ; Surround + DW Offset MixNoLoop, PreMix32Surround8Bit, MFS8Bit, MBS8Bit, Mix32Surround8Bit + DW Offset MixForwardsLoop, PreMix32Surround8Bit, MFS8Bit, MBS8Bit, Mix32Surround8Bit + DW Offset MixPingPongLoop, PreMix32Surround8Bit, MFS8Bit, MBS8Bit, Mix32Surround8Bit + + ; 16 bit tables + DW Offset UpdateNoLoop, 0, 0, 0, 0 ; Update only + DW Offset UpdateForwardsLoop, 0, 0, 0, 0 + DW Offset UpdatePingPongLoop, 0, 0, 0, 0 + ; Left only + DW Offset MixNoLoop, PreMix32Left16Bit, MFS16Bit, MBS16Bit, Mix32Single16Bit + DW Offset MixForwardsLoop, PreMix32Left16Bit, MFS16Bit, MBS16Bit, Mix32Single16Bit + DW Offset MixPingPongLoop, PreMix32Left16Bit, MFS16Bit, MBS16Bit, Mix32Single16Bit + ; Right only + DW Offset MixNoLoop, PreMix32Right16Bit, MFS16Bit, MBS16Bit, Mix32Single16Bit + DW Offset MixForwardsLoop, PreMix32Right16Bit, MFS16Bit, MBS16Bit, Mix32Single16Bit + DW Offset MixPingPongLoop, PreMix32Right16Bit, MFS16Bit, MBS16Bit, Mix32Single16Bit + ; Central + DW Offset MixNoLoop, PreMix32Central16Bit, MFS16Bit, MBS16Bit, Mix32Central16Bit + DW Offset MixForwardsLoop, PreMix32Central16Bit, MFS16Bit, MBS16Bit, Mix32Central16Bit + DW Offset MixPingPongLoop, PreMix32Central16Bit, MFS16Bit, MBS16Bit, Mix32Central16Bit + ; Stereo + DW Offset MixNoLoop, PreMix32Panned16Bit, MFS16Bit, MBS16Bit, Mix32Panned16Bit + DW Offset MixForwardsLoop, PreMix32Panned16Bit, MFS16Bit, MBS16Bit, Mix32Panned16Bit + DW Offset MixPingPongLoop, PreMix32Panned16Bit, MFS16Bit, MBS16Bit, Mix32Panned16Bit + ; Surround + DW Offset MixNoLoop, PreMix32Surround16Bit, MFS16Bit, MBS16Bit, Mix32Surround16Bit + DW Offset MixForwardsLoop, PreMix32Surround16Bit, MFS16Bit, MBS16Bit, Mix32Surround16Bit + DW Offset MixPingPongLoop, PreMix32Surround16Bit, MFS16Bit, MBS16Bit, Mix32Surround16Bit diff --git a/SoundDrivers/M32BIT.MIX b/SoundDrivers/M32BIT.MIX new file mode 100755 index 0000000..4a06c34 --- /dev/null +++ b/SoundDrivers/M32BIT.MIX @@ -0,0 +1,803 @@ + + ; Different mixing routines required: + ; Left } shared + ; Right } + ; Central + ; Surround + ; Panned ; Each requires 8 bit and 16 bit + ; Single output - for Mono, pure left/pure right + +M32Mix8Single Macro Index + +M32Mix8Single&Index&: + MovSX EBX, Byte Ptr [ES:DI] + +M32Mix8SingleVolume&Index& EQU $+3 + IMul EAX, EBX, 8000h + ShL EAX, 8 + + Add ERROR, DELTAERROR ;; 1 + AdC DI, DELTAOFFSET ;; 1 + Sub [SI+(Index-15)*8], EAX ;; 3 +EndM + +M32Mix8Central Macro Index + +M32Mix8Central&Index&: + MovSX EBX, Byte Ptr [ES:DI] ;; 4 + +M32Mix8CentralVolume&Index& EQU $+3 + IMul EAX, EBX, 8000h + ShL EAX, 8 ;; 4 + + Add ERROR, DELTAERROR ;; 1 + AdC DI, DELTAOFFSET ;; 1 + Sub [SI+(Index-15)*8], EAX ;; 4 + Sub [SI+(Index-15)*8+4], EAX ;; 4 + +EndM + +M32Mix8Surround Macro Index + +M32Mix8Surround&Index&: + MovSX EBX, Byte Ptr [ES:DI] ;; 4 + +M32Mix8SurroundVolume&Index& EQU $+3 + IMul EAX, EBX, 8000h + ShL EAX, 8 ;; 4 + + Add ERROR, DELTAERROR ;; 1 + AdC DI, DELTAOFFSET ;; 1 + Sub [SI+(Index-15)*8], EAX ;; 4 + Add [SI+(Index-15)*8+4], EAX ;; 4 + +EndM + + ; Panned output +M32Mix8Panned Macro Index + +M32Mix8Panned&Index&: + MovSX EBX, Byte Ptr [ES:DI] ;; 4 + +M32Mix8LeftVolume&Index& EQU $+3 + IMul EAX, EBX, 8000h +M32Mix8RightVolume&Index& EQU $+3 + IMul EBX, EBX, 8000h + + ShL EAX, 8 ;; 4 + ShL EBX, 8 ;; 4 + + Sub [SI+(Index-15)*8], EAX ;; 4 + Sub [SI+(Index-15)*8+4], EBX ;; 4 + + Add ERROR, DELTAERROR ;; 1 + AdC DI, DELTAOFFSET ;; 1 + +EndM + +M32Mix16Single Macro Index + +M32Mix16Single&Index&: + MovSX EBX, Word Ptr [ES:EDI+EDI] + +M32Mix16SingleVolume&Index& EQU $+3 + IMul EAX, EBX, 8000h + + Add ERROR, DELTAERROR ;; 1 + AdC DI, DELTAOFFSET ;; 1 + Sub [SI+(Index-15)*8], EAX ;; 3 + +EndM + +M32Mix16Central Macro Index + +M32Mix16Central&Index&: + MovSX EBX, Word Ptr [ES:EDI+EDI] + +M32Mix16CentralVolume&Index& EQU $+3 + IMul EAX, EBX, 8000h + + Add ERROR, DELTAERROR ;; 1 + AdC DI, DELTAOFFSET ;; 1 + Sub [SI+(Index-15)*8], EAX ;; 3 + Sub [SI+(Index-15)*8+4], EAX ;; 3 + +EndM + +M32Mix16Surround Macro Index + +M32Mix16Surround&Index&: + MovSX EBX, Word Ptr [ES:EDI+EDI] + +M32Mix16SurroundVolume&Index& EQU $+3 + IMul EAX, EBX, 8000h + + Add ERROR, DELTAERROR ;; 1 + AdC DI, DELTAOFFSET ;; 1 + Sub [SI+(Index-15)*8], EAX ;; 3 + Add [SI+(Index-15)*8+4], EAX ;; 3 + +EndM + + ; Panned output +M32Mix16Panned Macro Index + +M32Mix16Panned&Index&: + MovSX EBX, Word Ptr [ES:EDI+EDI] + +M32Mix16LeftVolume&Index& EQU $+3 + IMul EAX, EBX, 8000h +M32Mix16RightVolume&Index& EQU $+3 + IMul EBX, EBX, 8000h + + Sub [SI+(Index-15)*8], EAX + Sub [SI+(Index-15)*8+4], EBX + + Add ERROR, DELTAERROR + AdC DI, DELTAOFFSET + +EndM + +;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ + +Mix32Single8BitOffsetTable Label Word + + IndexCounter = 15 + + M32Mix8SingleOffset Macro Index + DW Offset M32Mix8Single&Index& + EndM + + REPT 16 + M32Mix8SingleOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix32Single8Bit + ; AX = count... + + ; Number of times to loop = (Count-1) / 16 + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Jmp [CS:Mix32Single8BitOffsetTable+BX] + + M32Mix8Single 0 + M32Mix8Single 1 + M32Mix8Single 2 + M32Mix8Single 3 + M32Mix8Single 4 + M32Mix8Single 5 + M32Mix8Single 6 + M32Mix8Single 7 + M32Mix8Single 8 + M32Mix8Single 9 + M32Mix8Single 10 + M32Mix8Single 11 + M32Mix8Single 12 + M32Mix8Single 13 + M32Mix8Single 14 + M32Mix8Single 15 + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ M32Mix8Single0 + + Ret + +EndP Mix32Single8Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix32Left8Bit + + Mov AX, [SI+0Eh] + +PreMix32Left8Bit1: + IndexCounter = 0 + + PreMix32SingleMacro Macro Index + Mov Word Ptr [CS:M32Mix8SingleVolume&Index&], AX + EndM + + REPT 16 + PreMix32SingleMacro %IndexCounter + IndexCounter = IndexCounter+1 + EndM + Ret + +EndP PreMix32Left8Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix32Right8Bit + + Add MixBufferOffset, MixResolution/8 + Mov AX, [SI+0Ch] + Jmp PreMix32Left8Bit1 + +EndP PreMix32Right8Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Mix32Central8BitOffsetTable Label Word + + IndexCounter = 15 + + M32Mix8CentralOffset Macro Index + DW Offset M32Mix8Central&Index& + EndM + + REPT 16 + M32Mix8CentralOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix32Central8Bit + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Jmp [CS:Mix32Central8BitOffsetTable+BX] + + M32Mix8Central 0 + M32Mix8Central 1 + M32Mix8Central 2 + M32Mix8Central 3 + M32Mix8Central 4 + M32Mix8Central 5 + M32Mix8Central 6 + M32Mix8Central 7 + M32Mix8Central 8 + M32Mix8Central 9 + M32Mix8Central 10 + M32Mix8Central 11 + M32Mix8Central 12 + M32Mix8Central 13 + M32Mix8Central 14 + M32Mix8Central 15 + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ M32Mix8Central0 + + Ret + +EndP Mix32Central8Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix32Central8Bit + + Mov AX, [SI+0Eh] + + IndexCounter = 0 + + PreMix32CentralMacro Macro Index + Mov Word Ptr [CS:M32Mix8CentralVolume&Index&], AX + EndM + + REPT 16 + PreMix32CentralMacro %IndexCounter + IndexCounter = IndexCounter+1 + EndM + + Ret + +EndP PreMix32Central8Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Mix32Surround8BitOffsetTable Label Word + + IndexCounter = 15 + + M32Mix8SurroundOffset Macro Index + DW Offset M32Mix8Surround&Index& + EndM + + REPT 16 + M32Mix8SurroundOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix32Surround8Bit + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Jmp [CS:Mix32Surround8BitOffsetTable+BX] + + M32Mix8Surround 0 + M32Mix8Surround 1 + M32Mix8Surround 2 + M32Mix8Surround 3 + M32Mix8Surround 4 + M32Mix8Surround 5 + M32Mix8Surround 6 + M32Mix8Surround 7 + M32Mix8Surround 8 + M32Mix8Surround 9 + M32Mix8Surround 10 + M32Mix8Surround 11 + M32Mix8Surround 12 + M32Mix8Surround 13 + M32Mix8Surround 14 + M32Mix8Surround 15 + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ M32Mix8Surround0 + + Ret + +EndP Mix32Surround8Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix32Surround8Bit + + Mov AX, [SI+0Eh] + + IndexCounter = 0 + + PreMix32SurroundMacro Macro Index + Mov Word Ptr [CS:M32Mix8SurroundVolume&Index&], AX + EndM + + REPT 16 + PreMix32SurroundMacro %IndexCounter + IndexCounter = IndexCounter+1 + EndM + + Ret + +EndP PreMix32Surround8Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Mix32Panned8BitOffsetTable Label Word + + IndexCounter = 15 + + M32Mix8PannedOffset Macro Index + DW Offset M32Mix8Panned&Index& + EndM + + REPT 16 + M32Mix8PannedOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix32Panned8Bit + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Jmp [CS:Mix32Panned8BitOffsetTable+BX] + + M32Mix8Panned 0 + M32Mix8Panned 1 + M32Mix8Panned 2 + M32Mix8Panned 3 + M32Mix8Panned 4 + M32Mix8Panned 5 + M32Mix8Panned 6 + M32Mix8Panned 7 + M32Mix8Panned 8 + M32Mix8Panned 9 + M32Mix8Panned 10 + M32Mix8Panned 11 + M32Mix8Panned 12 + M32Mix8Panned 13 + M32Mix8Panned 14 + M32Mix8Panned 15 + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ M32Mix8Panned0 + + Ret + +EndP Mix32Panned8Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix32Panned8Bit + + Mov AX, [SI+0Eh] ; Left + Mov BX, [SI+0Ch] ; Right + + IndexCounter = 0 + + PreMix32PannedMacro Macro Index + Mov Word Ptr [CS:M32Mix8LeftVolume&Index&], AX + Mov Word Ptr [CS:M32Mix8RightVolume&Index&], BX + EndM + + REPT 16 + PreMix32PannedMacro %IndexCounter + IndexCounter = IndexCounter+1 + EndM + + Ret + +EndP PreMix32Panned8Bit + +;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ + +Mix32Single16BitOffsetTable Label Word + + IndexCounter = 15 + + M32Mix16SingleOffset Macro Index + DW Offset M32Mix16Single&Index& + EndM + + REPT 16 + M32Mix16SingleOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix32Single16Bit + ; AX = count... + + ; Number of times to loop = (Count-1) / 16 + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Jmp [CS:Mix32Single16BitOffsetTable+BX] + + M32Mix16Single 0 + M32Mix16Single 1 + M32Mix16Single 2 + M32Mix16Single 3 + M32Mix16Single 4 + M32Mix16Single 5 + M32Mix16Single 6 + M32Mix16Single 7 + M32Mix16Single 8 + M32Mix16Single 9 + M32Mix16Single 10 + M32Mix16Single 11 + M32Mix16Single 12 + M32Mix16Single 13 + M32Mix16Single 14 + M32Mix16Single 15 + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ M32Mix16Single0 + + Ret + +EndP Mix32Single16Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix32Left16Bit + + Mov AX, [SI+0Eh] ; Left + +PreMix32Left16Bit1: + IndexCounter = 0 + + PreMix32SingleMacro Macro Index + Mov Word Ptr [CS:M32Mix16SingleVolume&Index&], AX + EndM + + REPT 16 + PreMix32SingleMacro %IndexCounter + IndexCounter = IndexCounter+1 + EndM + + Ret + +EndP PreMix32Left16Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix32Right16Bit + + Add MixBufferOffset, MixResolution/8 + Mov AX, [SI+0Ch] + Jmp PreMix32Left16Bit1 + + Ret + +EndP PreMix32Right16Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Mix32Central16BitOffsetTable Label Word + + IndexCounter = 15 + + M32Mix16CentralOffset Macro Index + DW Offset M32Mix16Central&Index& + EndM + + REPT 16 + M32Mix16CentralOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix32Central16Bit + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Jmp [CS:Mix32Central16BitOffsetTable+BX] + + M32Mix16Central 0 + M32Mix16Central 1 + M32Mix16Central 2 + M32Mix16Central 3 + M32Mix16Central 4 + M32Mix16Central 5 + M32Mix16Central 6 + M32Mix16Central 7 + M32Mix16Central 8 + M32Mix16Central 9 + M32Mix16Central 10 + M32Mix16Central 11 + M32Mix16Central 12 + M32Mix16Central 13 + M32Mix16Central 14 + M32Mix16Central 15 + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ M32Mix16Central0 + + Ret + +EndP Mix32Central16Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix32Central16Bit + + Mov AX, [SI+0Eh] + + IndexCounter = 0 + + PreMix32CentralMacro Macro Index + Mov Word Ptr [CS:M32Mix16CentralVolume&Index&], AX + EndM + + REPT 16 + PreMix32CentralMacro %IndexCounter + IndexCounter = IndexCounter+1 + EndM + + Ret + +EndP PreMix32Central16Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Mix32Surround16BitOffsetTable Label Word + + IndexCounter = 15 + + M32Mix16SurroundOffset Macro Index + DW Offset M32Mix16Surround&Index& + EndM + + REPT 16 + M32Mix16SurroundOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix32Surround16Bit + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Jmp [CS:Mix32Surround16BitOffsetTable+BX] + + M32Mix16Surround 0 + M32Mix16Surround 1 + M32Mix16Surround 2 + M32Mix16Surround 3 + M32Mix16Surround 4 + M32Mix16Surround 5 + M32Mix16Surround 6 + M32Mix16Surround 7 + M32Mix16Surround 8 + M32Mix16Surround 9 + M32Mix16Surround 10 + M32Mix16Surround 11 + M32Mix16Surround 12 + M32Mix16Surround 13 + M32Mix16Surround 14 + M32Mix16Surround 15 + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ M32Mix16Surround0 + + Ret + +EndP Mix32Surround16Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix32Surround16Bit + + Mov AX, [SI+0Eh] + + IndexCounter = 0 + + PreMix32SurroundMacro Macro Index + Mov Word Ptr [CS:M32Mix16SurroundVolume&Index&], AX + EndM + + REPT 16 + PreMix32SurroundMacro %IndexCounter + IndexCounter = IndexCounter+1 + EndM + + Ret + +EndP PreMix32Surround16Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Mix32Panned16BitOffsetTable Label Word + + IndexCounter = 15 + + M32Mix16PannedOffset Macro Index + DW Offset M32Mix16Panned&Index& + EndM + + REPT 16 + M32Mix16PannedOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix32Panned16Bit + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Jmp [CS:Mix32Panned16BitOffsetTable+BX] + +Pan32Bit16Loop: + M32Mix16Panned 0 + M32Mix16Panned 1 + M32Mix16Panned 2 + M32Mix16Panned 3 + M32Mix16Panned 4 + M32Mix16Panned 5 + M32Mix16Panned 6 + M32Mix16Panned 7 + M32Mix16Panned 8 + M32Mix16Panned 9 + M32Mix16Panned 10 + M32Mix16Panned 11 + M32Mix16Panned 12 + M32Mix16Panned 13 + M32Mix16Panned 14 + M32Mix16Panned 15 + + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ Pan32Bit16Loop + + Ret + +EndP Mix32Panned16Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix32Panned16Bit + + Mov AX, [SI+0Eh] ; Left + Mov BX, [SI+0Ch] ; Right + + IndexCounter = 0 + + PreMix32PannedMacro Macro Index + Mov Word Ptr [CS:M32Mix16LeftVolume&Index&], AX + Mov Word Ptr [CS:M32Mix16RightVolume&Index&], BX + EndM + + REPT 16 + PreMix32PannedMacro %IndexCounter + IndexCounter = IndexCounter+1 + EndM + + Ret + +EndP PreMix32Panned16Bit + + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + diff --git a/SoundDrivers/M32BITFF.MIX b/SoundDrivers/M32BITFF.MIX new file mode 100755 index 0000000..6a6abcd --- /dev/null +++ b/SoundDrivers/M32BITFF.MIX @@ -0,0 +1,6 @@ +; +; Floating point mixing routines +; DS:0 = a, DS:4 = b, DS:8 = c +; DS:10h = os1, DS:18h = OS2 +; + diff --git a/SoundDrivers/M32BITI.INC b/SoundDrivers/M32BITI.INC new file mode 100755 index 0000000..4a229ab --- /dev/null +++ b/SoundDrivers/M32BITI.INC @@ -0,0 +1,49 @@ + + DW Offset UpdateNoLoop, 0, 0, 0, 0 ; Update only + DW Offset UpdateForwardsLoop, 0, 0, 0, 0 + DW Offset UpdatePingPongLoop, 0, 0, 0, 0 + ; Left only + DW Offset MixNoLoop, PreMix32Left8BitI, MFS8Bit, MBS8Bit, Mix32Single8BitI + DW Offset MixForwardsLoop, PreMix32Left8BitI, MFS8Bit, MBS8Bit, Mix32Single8BitI + DW Offset MixPingPongLoop, PreMix32Left8BitI, MFS8Bit, MBS8Bit, Mix32Single8BitI + ; Right only + DW Offset MixNoLoop, PreMix32Right8BitI, MFS8Bit, MBS8Bit, Mix32Single8BitI + DW Offset MixForwardsLoop, PreMix32Right8BitI, MFS8Bit, MBS8Bit, Mix32Single8BitI + DW Offset MixPingPongLoop, PreMix32Right8BitI, MFS8Bit, MBS8Bit, Mix32Single8BitI + ; Central + DW Offset MixNoLoop, PreMix32Central8BitI, MFS8Bit, MBS8Bit, Mix32Central8BitI + DW Offset MixForwardsLoop, PreMix32Central8BitI, MFS8Bit, MBS8Bit, Mix32Central8BitI + DW Offset MixPingPongLoop, PreMix32Central8BitI, MFS8Bit, MBS8Bit, Mix32Central8BitI + ; Stereo + DW Offset MixNoLoop, PreMix32Panned8BitI, MFS8Bit, MBS8Bit, Mix32Panned8BitI + DW Offset MixForwardsLoop, PreMix32Panned8BitI, MFS8Bit, MBS8Bit, Mix32Panned8BitI + DW Offset MixPingPongLoop, PreMix32Panned8BitI, MFS8Bit, MBS8Bit, Mix32Panned8BitI + ; Surround + DW Offset MixNoLoop, PreMix32Surround8BitI, MFS8Bit, MBS8Bit, Mix32Surround8BitI + DW Offset MixForwardsLoop, PreMix32Surround8BitI, MFS8Bit, MBS8Bit, Mix32Surround8BitI + DW Offset MixPingPongLoop, PreMix32Surround8BitI, MFS8Bit, MBS8Bit, Mix32Surround8BitI + + ; 16 bit tables + DW Offset UpdateNoLoop, 0, 0, 0, 0 ; Update only + DW Offset UpdateForwardsLoop, 0, 0, 0, 0 + DW Offset UpdatePingPongLoop, 0, 0, 0, 0 + ; Left only + DW Offset MixNoLoop, PreMix32Left16BitI, MFS16Bit, MBS16Bit, Mix32Single16BitI + DW Offset MixForwardsLoop, PreMix32Left16BitI, MFS16Bit, MBS16Bit, Mix32Single16BitI + DW Offset MixPingPongLoop, PreMix32Left16BitI, MFS16Bit, MBS16Bit, Mix32Single16BitI + ; Right only + DW Offset MixNoLoop, PreMix32Right16BitI, MFS16Bit, MBS16Bit, Mix32Single16BitI + DW Offset MixForwardsLoop, PreMix32Right16BitI, MFS16Bit, MBS16Bit, Mix32Single16BitI + DW Offset MixPingPongLoop, PreMix32Right16BitI, MFS16Bit, MBS16Bit, Mix32Single16BitI + ; Central + DW Offset MixNoLoop, PreMix32Central16BitI, MFS16Bit, MBS16Bit, Mix32Central16BitI + DW Offset MixForwardsLoop, PreMix32Central16BitI, MFS16Bit, MBS16Bit, Mix32Central16BitI + DW Offset MixPingPongLoop, PreMix32Central16BitI, MFS16Bit, MBS16Bit, Mix32Central16BitI + ; Stereo + DW Offset MixNoLoop, PreMix32Panned16BitI, MFS16Bit, MBS16Bit, Mix32Panned16BitI + DW Offset MixForwardsLoop, PreMix32Panned16BitI, MFS16Bit, MBS16Bit, Mix32Panned16BitI + DW Offset MixPingPongLoop, PreMix32Panned16BitI, MFS16Bit, MBS16Bit, Mix32Panned16BitI + ; Surround + DW Offset MixNoLoop, PreMix32Surround16BitI, MFS16Bit, MBS16Bit, Mix32Surround16BitI + DW Offset MixForwardsLoop, PreMix32Surround16BitI, MFS16Bit, MBS16Bit, Mix32Surround16BitI + DW Offset MixPingPongLoop, PreMix32Surround16BitI, MFS16Bit, MBS16Bit, Mix32Surround16BitI diff --git a/SoundDrivers/M32BITI.MIX b/SoundDrivers/M32BITI.MIX new file mode 100755 index 0000000..6d645dd --- /dev/null +++ b/SoundDrivers/M32BITI.MIX @@ -0,0 +1,818 @@ + + ; Different mixing routines required: + ; Left } shared + ; Right } + ; Central + ; Surround + ; Panned ; Each requires 8 bit and 16 bit + ; Single output - for Mono, pure left/pure right + +Get32Bit8Waveform Macro + MovSX EBX, Byte Ptr [ES:DI+1] + MovSX EAX, Byte Ptr [ES:DI] + Sub EBX, EAX + IMul EBX, ECX + SAR EBX, 8 + ShL EAX, 8 + Add EBX, EAX + +EndM + +Get32Bit16Waveform Macro + MovSX EBX, Word Ptr [ES:EDI+EDI+2] + MovSX EAX, Word Ptr [ES:EDI+EDI] + Sub EBX, EAX + SAR EBX, 1 + IMul EBX, ECX + SAR EBX, 15 + Add EBX, EAX +EndM + +M32Mix8ISingle Macro Index + +M32Mix8ISingle&Index&: + Get32Bit8WaveForm + +M32Mix8ISingleVolume&Index& EQU $+3 + IMul EAX, EBX, 8000h + + Add ERROR, DELTAERROR ;; 1 + AdC DI, DELTAOFFSET ;; 1 + Sub [SI+(Index-15)*8], EAX ;; 3 +EndM + +M32Mix8ICentral Macro Index + +M32Mix8ICentral&Index&: + Get32Bit8WaveForm + +M32Mix8ICentralVolume&Index& EQU $+3 + IMul EAX, EBX, 8000h + + Add ERROR, DELTAERROR ;; 1 + AdC DI, DELTAOFFSET ;; 1 + Sub [SI+(Index-15)*8], EAX ;; 4 + Sub [SI+(Index-15)*8+4], EAX ;; 4 + +EndM + +M32Mix8ISurround Macro Index + +M32Mix8ISurround&Index&: + Get32Bit8WaveForm + +M32Mix8ISurroundVolume&Index& EQU $+3 + IMul EAX, EBX, 8000h + + Add ERROR, DELTAERROR ;; 1 + AdC DI, DELTAOFFSET ;; 1 + Sub [SI+(Index-15)*8], EAX ;; 4 + Add [SI+(Index-15)*8+4], EAX ;; 4 + +EndM + + ; Panned output +M32Mix8IPanned Macro Index + +M32Mix8IPanned&Index&: + Get32Bit8WaveForm + +M32Mix8ILeftVolume&Index& EQU $+3 + IMul EAX, EBX, 8000h +M32Mix8IRightVolume&Index& EQU $+3 + IMul EBX, EBX, 8000h + + Sub [SI+(Index-15)*8], EAX ;; 4 + Sub [SI+(Index-15)*8+4], EBX ;; 4 + + Add ERROR, DELTAERROR ;; 1 + AdC DI, DELTAOFFSET ;; 1 + +EndM + +M32Mix16ISingle Macro Index + +M32Mix16ISingle&Index&: + Get32Bit16WaveForm + +M32Mix16ISingleVolume&Index& EQU $+3 + IMul EAX, EBX, 8000h + + Add ERROR, DELTAERROR ;; 1 + AdC DI, DELTAOFFSET ;; 1 + Sub [SI+(Index-15)*8], EAX ;; 3 + +EndM + +M32Mix16ICentral Macro Index + +M32Mix16ICentral&Index&: + Get32Bit16WaveForm + +M32Mix16ICentralVolume&Index& EQU $+3 + IMul EAX, EBX, 8000h + + Add ERROR, DELTAERROR ;; 1 + AdC DI, DELTAOFFSET ;; 1 + Sub [SI+(Index-15)*8], EAX ;; 3 + Sub [SI+(Index-15)*8+4], EAX ;; 3 + +EndM + +M32Mix16ISurround Macro Index + +M32Mix16ISurround&Index&: + Get32Bit16WaveForm + +M32Mix16ISurroundVolume&Index& EQU $+3 + IMul EAX, EBX, 8000h + + Add ERROR, DELTAERROR ;; 1 + AdC DI, DELTAOFFSET ;; 1 + Sub [SI+(Index-15)*8], EAX ;; 3 + Add [SI+(Index-15)*8+4], EAX ;; 3 + +EndM + + ; Panned output +M32Mix16IPanned Macro Index + +M32Mix16IPanned&Index&: + Get32Bit16WaveForm + +M32Mix16ILeftVolume&Index& EQU $+3 + IMul EAX, EBX, 8000h +M32Mix16IRightVolume&Index& EQU $+3 + IMul EBX, EBX, 8000h + + Sub [SI+(Index-15)*8], EAX + Sub [SI+(Index-15)*8+4], EBX + + Add ERROR, DELTAERROR + AdC DI, DELTAOFFSET + +EndM + +;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ + +Mix32Single8BitIOffsetTable Label Word + + IndexCounter = 15 + + M32Mix8ISingleOffset Macro Index + DW Offset M32Mix8ISingle&Index& + EndM + + REPT 16 + M32Mix8ISingleOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix32Single8BitI + ; AX = count... + + ; Number of times to loop = (Count-1) / 16 + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Jmp [CS:Mix32Single8BitIOffsetTable+BX] + + M32Mix8ISingle 0 + M32Mix8ISingle 1 + M32Mix8ISingle 2 + M32Mix8ISingle 3 + M32Mix8ISingle 4 + M32Mix8ISingle 5 + M32Mix8ISingle 6 + M32Mix8ISingle 7 + M32Mix8ISingle 8 + M32Mix8ISingle 9 + M32Mix8ISingle 10 + M32Mix8ISingle 11 + M32Mix8ISingle 12 + M32Mix8ISingle 13 + M32Mix8ISingle 14 + M32Mix8ISingle 15 + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ M32Mix8ISingle0 + + Ret + +EndP Mix32Single8BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix32Left8BitI + + Mov AX, [SI+0Eh] + +PreMix32Left8BitI1: + IndexCounter = 0 + + PreMix32SingleMacro Macro Index + Mov Word Ptr [CS:M32Mix8ISingleVolume&Index&], AX + EndM + + REPT 16 + PreMix32SingleMacro %IndexCounter + IndexCounter = IndexCounter+1 + EndM + Ret + +EndP PreMix32Left8BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix32Right8BitI + + Add MixBufferOffset, MixResolution/8 + Mov AX, [SI+0Ch] + Jmp PreMix32Left8BitI1 + +EndP PreMix32Right8BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Mix32Central8BitIOffsetTable Label Word + + IndexCounter = 15 + + M32Mix8ICentralOffset Macro Index + DW Offset M32Mix8ICentral&Index& + EndM + + REPT 16 + M32Mix8ICentralOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix32Central8BitI + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Jmp [CS:Mix32Central8BitIOffsetTable+BX] + + M32Mix8ICentral 0 + M32Mix8ICentral 1 + M32Mix8ICentral 2 + M32Mix8ICentral 3 + M32Mix8ICentral 4 + M32Mix8ICentral 5 + M32Mix8ICentral 6 + M32Mix8ICentral 7 + M32Mix8ICentral 8 + M32Mix8ICentral 9 + M32Mix8ICentral 10 + M32Mix8ICentral 11 + M32Mix8ICentral 12 + M32Mix8ICentral 13 + M32Mix8ICentral 14 + M32Mix8ICentral 15 + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ M32Mix8ICentral0 + + Ret + +EndP Mix32Central8BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix32Central8BitI + + Mov AX, [SI+0Eh] + + IndexCounter = 0 + + PreMix32CentralMacro Macro Index + Mov Word Ptr [CS:M32Mix8ICentralVolume&Index&], AX + EndM + + REPT 16 + PreMix32CentralMacro %IndexCounter + IndexCounter = IndexCounter+1 + EndM + + Ret + +EndP PreMix32Central8BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Mix32Surround8BitIOffsetTable Label Word + + IndexCounter = 15 + + M32Mix8ISurroundOffset Macro Index + DW Offset M32Mix8ISurround&Index& + EndM + + REPT 16 + M32Mix8ISurroundOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix32Surround8BitI + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Jmp [CS:Mix32Surround8BitIOffsetTable+BX] + + M32Mix8ISurround 0 + M32Mix8ISurround 1 + M32Mix8ISurround 2 + M32Mix8ISurround 3 + M32Mix8ISurround 4 + M32Mix8ISurround 5 + M32Mix8ISurround 6 + M32Mix8ISurround 7 + M32Mix8ISurround 8 + M32Mix8ISurround 9 + M32Mix8ISurround 10 + M32Mix8ISurround 11 + M32Mix8ISurround 12 + M32Mix8ISurround 13 + M32Mix8ISurround 14 + M32Mix8ISurround 15 + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ M32Mix8ISurround0 + + Ret + +EndP Mix32Surround8BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix32Surround8BitI + + Mov AX, [SI+0Eh] + + IndexCounter = 0 + + PreMix32SurroundMacro Macro Index + Mov Word Ptr [CS:M32Mix8ISurroundVolume&Index&], AX + EndM + + REPT 16 + PreMix32SurroundMacro %IndexCounter + IndexCounter = IndexCounter+1 + EndM + + Ret + +EndP PreMix32Surround8BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Mix32Panned8BitIOffsetTable Label Word + + IndexCounter = 15 + + M32Mix8IPannedOffset Macro Index + DW Offset M32Mix8IPanned&Index& + EndM + + REPT 16 + M32Mix8IPannedOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix32Panned8BitI + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Jmp [CS:Mix32Panned8BitIOffsetTable+BX] + + M32Mix8IPanned 0 + M32Mix8IPanned 1 + M32Mix8IPanned 2 + M32Mix8IPanned 3 + M32Mix8IPanned 4 + M32Mix8IPanned 5 + M32Mix8IPanned 6 + M32Mix8IPanned 7 + M32Mix8IPanned 8 + M32Mix8IPanned 9 + M32Mix8IPanned 10 + M32Mix8IPanned 11 + M32Mix8IPanned 12 + M32Mix8IPanned 13 + M32Mix8IPanned 14 + M32Mix8IPanned 15 + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ M32Mix8IPanned0 + + Ret + +EndP Mix32Panned8BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix32Panned8BitI + + Mov AX, [SI+0Eh] ; Left + Mov BX, [SI+0Ch] ; Right + + IndexCounter = 0 + + PreMix32PannedMacro Macro Index + Mov Word Ptr [CS:M32Mix8ILeftVolume&Index&], AX + Mov Word Ptr [CS:M32Mix8IRightVolume&Index&], BX + EndM + + REPT 16 + PreMix32PannedMacro %IndexCounter + IndexCounter = IndexCounter+1 + EndM + + Ret + +EndP PreMix32Panned8BitI + +;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ + +Mix32Single16BitIOffsetTable Label Word + + IndexCounter = 15 + + M32Mix16ISingleOffset Macro Index + DW Offset M32Mix16ISingle&Index& + EndM + + REPT 16 + M32Mix16ISingleOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix32Single16BitI + ; AX = count... + + ; Number of times to loop = (Count-1) / 16 + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Jmp [CS:Mix32Single16BitIOffsetTable+BX] + + M32Mix16ISingle 0 + M32Mix16ISingle 1 + M32Mix16ISingle 2 + M32Mix16ISingle 3 + M32Mix16ISingle 4 + M32Mix16ISingle 5 + M32Mix16ISingle 6 + M32Mix16ISingle 7 + M32Mix16ISingle 8 + M32Mix16ISingle 9 + M32Mix16ISingle 10 + M32Mix16ISingle 11 + M32Mix16ISingle 12 + M32Mix16ISingle 13 + M32Mix16ISingle 14 + M32Mix16ISingle 15 + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ M32Mix16ISingle0 + + Ret + +EndP Mix32Single16BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix32Left16BitI + + Mov AX, [SI+0Eh] ; Left + +PreMix32Left16BitI1: + IndexCounter = 0 + + PreMix32SingleMacro Macro Index + Mov Word Ptr [CS:M32Mix16ISingleVolume&Index&], AX + EndM + + REPT 16 + PreMix32SingleMacro %IndexCounter + IndexCounter = IndexCounter+1 + EndM + + Ret + +EndP PreMix32Left16BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix32Right16BitI + + Add MixBufferOffset, MixResolution/8 + Mov AX, [SI+0Ch] + Jmp PreMix32Left16BitI1 + + Ret + +EndP PreMix32Right16BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Mix32Central16BitIOffsetTable Label Word + + IndexCounter = 15 + + M32Mix16ICentralOffset Macro Index + DW Offset M32Mix16ICentral&Index& + EndM + + REPT 16 + M32Mix16ICentralOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix32Central16BitI + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Jmp [CS:Mix32Central16BitIOffsetTable+BX] + + M32Mix16ICentral 0 + M32Mix16ICentral 1 + M32Mix16ICentral 2 + M32Mix16ICentral 3 + M32Mix16ICentral 4 + M32Mix16ICentral 5 + M32Mix16ICentral 6 + M32Mix16ICentral 7 + M32Mix16ICentral 8 + M32Mix16ICentral 9 + M32Mix16ICentral 10 + M32Mix16ICentral 11 + M32Mix16ICentral 12 + M32Mix16ICentral 13 + M32Mix16ICentral 14 + M32Mix16ICentral 15 + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ M32Mix16ICentral0 + + Ret + +EndP Mix32Central16BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix32Central16BitI + + Mov AX, [SI+0Eh] + + IndexCounter = 0 + + PreMix32CentralMacro Macro Index + Mov Word Ptr [CS:M32Mix16ICentralVolume&Index&], AX + EndM + + REPT 16 + PreMix32CentralMacro %IndexCounter + IndexCounter = IndexCounter+1 + EndM + + Ret + +EndP PreMix32Central16BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Mix32Surround16BitIOffsetTable Label Word + + IndexCounter = 15 + + M32Mix16ISurroundOffset Macro Index + DW Offset M32Mix16ISurround&Index& + EndM + + REPT 16 + M32Mix16ISurroundOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix32Surround16BitI + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Jmp [CS:Mix32Surround16BitIOffsetTable+BX] + + M32Mix16ISurround 0 + M32Mix16ISurround 1 + M32Mix16ISurround 2 + M32Mix16ISurround 3 + M32Mix16ISurround 4 + M32Mix16ISurround 5 + M32Mix16ISurround 6 + M32Mix16ISurround 7 + M32Mix16ISurround 8 + M32Mix16ISurround 9 + M32Mix16ISurround 10 + M32Mix16ISurround 11 + M32Mix16ISurround 12 + M32Mix16ISurround 13 + M32Mix16ISurround 14 + M32Mix16ISurround 15 + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ M32Mix16ISurround0 + + Ret + +EndP Mix32Surround16BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix32Surround16BitI + + Mov AX, [SI+0Eh] + + IndexCounter = 0 + + PreMix32SurroundMacro Macro Index + Mov Word Ptr [CS:M32Mix16ISurroundVolume&Index&], AX + EndM + + REPT 16 + PreMix32SurroundMacro %IndexCounter + IndexCounter = IndexCounter+1 + EndM + + Ret + +EndP PreMix32Surround16BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Mix32Panned16BitIOffsetTable Label Word + + IndexCounter = 15 + + M32Mix16IPannedOffset Macro Index + DW Offset M32Mix16IPanned&Index& + EndM + + REPT 16 + M32Mix16IPannedOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix32Panned16BitI + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Jmp [CS:Mix32Panned16BitIOffsetTable+BX] + +Pan32Bit16ILoop: + M32Mix16IPanned 0 + M32Mix16IPanned 1 + M32Mix16IPanned 2 + M32Mix16IPanned 3 + M32Mix16IPanned 4 + M32Mix16IPanned 5 + M32Mix16IPanned 6 + M32Mix16IPanned 7 + M32Mix16IPanned 8 + M32Mix16IPanned 9 + M32Mix16IPanned 10 + M32Mix16IPanned 11 + M32Mix16IPanned 12 + M32Mix16IPanned 13 + M32Mix16IPanned 14 + M32Mix16IPanned 15 + + + Add SI, 16*MIXRESOLUTION/4 + Dec LoopCounter + JNZ Pan32Bit16ILoop + + Ret + +EndP Mix32Panned16BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix32Panned16BitI + + Mov AX, [SI+0Eh] ; Left + Mov BX, [SI+0Ch] ; Right + + IndexCounter = 0 + + PreMix32PannedMacro Macro Index + Mov Word Ptr [CS:M32Mix16ILeftVolume&Index&], AX + Mov Word Ptr [CS:M32Mix16IRightVolume&Index&], BX + EndM + + REPT 16 + PreMix32PannedMacro %IndexCounter + IndexCounter = IndexCounter+1 + EndM + + Ret + +EndP PreMix32Panned16BitI + + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + diff --git a/SoundDrivers/M32BITM.INC b/SoundDrivers/M32BITM.INC new file mode 100755 index 0000000..8a12847 --- /dev/null +++ b/SoundDrivers/M32BITM.INC @@ -0,0 +1,11 @@ +; 8 bit tables + + DW Offset MixNoLoop, PreM32BitMPanned, MFS8Bit, MBS8Bit, M32Bit8MPanned + DW Offset MixForwardsLoop, PreM32BitMPanned, MFS8Bit, MBS8Bit, M32Bit8MPanned + DW Offset MixPingPongLoop, PreM32BitMPanned, MFS8Bit, MBS8Bit, M32Bit8MPanned + +; 16 bit + + DW Offset MixNoLoop, PreM32BitMPanned, MFS16Bit, MBS16Bit, M32Bit16MPanned + DW Offset MixForwardsLoop, PreM32BitMPanned, MFS16Bit, MBS16Bit, M32Bit16MPanned + DW Offset MixPingPongLoop, PreM32BitMPanned, MFS16Bit, MBS16Bit, M32Bit16MPanned diff --git a/SoundDrivers/M32BITM.MIX b/SoundDrivers/M32BITM.MIX new file mode 100755 index 0000000..33f837a --- /dev/null +++ b/SoundDrivers/M32BITM.MIX @@ -0,0 +1,502 @@ + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MONITORPERFORMANCE = 0 + +ALIGN 16 + +M32BitMVolumeData DW 0, 0, 0, 0 + +IF MONITORPERFORMANCE +M32BitMCounter8BitTicksLow DD 0 +M32BitMCounter8BitTicksHigh DD 0 +M32BitMCounter16BitTicksLow DD 0 +M32BitMCounter16BitTicksHigh DD 0 +M32BitMCounter8BitLow DW 0 +M32BitMCounter8BitHigh DW 0 +M32BitMCounter16BitLow DW 0 +M32BitMCounter16BitHigh DW 0 +ENDIF + + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc M32Bit16MPanned + +; AX = number to mix +; CX = error +; DX = deltaoffset +; BP = deltaerror +; DS:SI = 32-bit output buffer +; ES:EDI+EDI = sample location +; MM6 = L/R volumes +; MM7 = PXor mask + +IF MONITORPERFORMANCE + Push EAX + Push EDX + + Add CS:M32BitMCounter16BitLow, AX + AdC CS:M32BitMCounter16BitHigh, 0 + + RdTSC + Sub CS:M32BitMCounter16BitTicksLow, EAX + SBB CS:M32BitMCounter16BitTicksHigh, EDX + + Pop EDX + Pop EAX +ENDIF + + Mov BX, DI + Add BX, BX + +M32Bit16MPanned1: ; Mix 1 sample + Test AL, 1 + JZ M32Bit16MPanned2 + + Push AX + Add CX, BP + Mov AX, [ES:BX] + AdC DI, DX + Mov [DS:0], AX + Mov BX, DI + + MovQ MM0, [DS:0] + Add BX, BX + + PUnpckLWD MM0, MM0 + MovQ MM2, MM6 + PMulLW MM2, MM0 + PMulHW MM0, MM6 + PUnpckLWD MM2, MM0 + PAddD MM2, [SI] + MovQM [SI], MM2 + + Add SI, 8 + Pop AX + +M32Bit16MPanned2: ; Mix 2 samples + Test AL, 2 + JZ M32Bit16MPanned3 + + Push AX + Add CX, BP + Mov AX, [ES:BX] + AdC DI, DX + Mov [DS:0], AX + Mov BX, DI + Add BX, BX + Add CX, BP + AdC DI, DX + Mov AX, [ES:BX] + Mov BX, DI + Mov [DS:2], AX + Add BX, BX + + MovQ MM0, [DS:0] + PUnpckLWD MM0, MM0 + MovQ MM2, MM6 + PMulLW MM2, MM0 + PMulHW MM0, MM6 + MovQ MM4, MM2 + PUnpckLWD MM2, MM0 + PUnpckHWD MM4, MM0 + PAddD MM2, [SI] + PAddD MM4, [SI+8] + MovQM [SI], MM2 + MovQM [SI+8], MM4 + + Add SI, 10h + Pop AX + +M32Bit16MPanned3: + ShR AX, 2 + JZ M32Bit16MPannedEnd + + Mov Word Ptr [DS:20h], AX + + Mov AX, [ES:BX] + Add CX, BP + AdC DI, DX + Mov [DS:0], AX + Mov BX, DI + Add BX, BX + + Mov AX, [ES:BX] + Add CX, BP + AdC DI, DX + Mov [DS:2], AX + Mov BX, DI + Add BX, BX + + Mov AX, [ES:BX] + Add CX, BP + AdC DI, DX + Mov [DS:0Ch], AX + Mov BX, DI + Add BX, BX + + Mov AX, [ES:BX] + Add CX, BP + AdC DI, DX + Mov [DS:0Eh], AX + Mov BX, DI + Add BX, BX + + Dec Word Ptr [DS:20h] + JZ M32Bit16MPanned5 + +M32Bit16MPanned4: + MovQ MM0, [DS:0] + MovQ MM2, MM6 + MovQ MM1, [DS:8] + PUnpckLWD MM0, MM0 + + PMulLW MM2, MM0 + PUnpckHWD MM1, MM1 + + PMulHW MM0, MM6 + MovQ MM3, MM6 + + Mov AX, [ES:BX] + Add CX, BP + AdC DI, DX + Mov [DS:0], AX + Mov BX, DI + Add BX, BX + + MovQ MM4, MM2 + PUnpckLWD MM2, MM0 + + PAddD MM2, [SI] + PUnpckHWD MM4, MM0 + + PAddD MM4, [SI+8] + PMulLW MM3, MM1 + + MovQM [SI], MM2 + PMulHW MM1, MM6 + + Mov AX, [ES:BX] + Add CX, BP + AdC DI, DX + Mov [DS:2], AX + Mov BX, DI + Add BX, BX + + MovQM [SI+8], MM4 + MovQ MM5, MM3 + + MovQ MM0, [SI+18h] + PUnpckLWD MM3, MM1 + PAddD MM3, [SI+10h] + PUnpckHWD MM5, MM1 + MovQM [SI+10h], MM3 + PAddD MM5, MM0 + + Mov AX, [ES:BX] + Add CX, BP + AdC DI, DX + Mov [DS:0Ch], AX + Mov BX, DI + Add BX, BX + + MovQM [SI+18h], MM5 + + Mov AX, [ES:BX] + Add CX, BP + AdC DI, DX + Mov [DS:0Eh], AX + Mov BX, DI + Add BX, BX + + Add SI, 20h + + Dec Word Ptr [DS:20h] + JNZ M32Bit16MPanned4 + +M32Bit16MPanned5: + MovQ MM0, [DS:0] + MovQ MM2, MM6 + + MovQ MM1, [DS:8] + PUnpckLWD MM0, MM0 + + PMulLW MM2, MM0 + MovQ MM3, MM6 + + PMulHW MM0, MM6 + PUnpckHWD MM1, MM1 + + MovQ MM4, MM2 + PMulLW MM3, MM1 + + PUnpckLWD MM2, MM0 + PMulHW MM1, MM6 + + PAddD MM2, [SI] + PUnpckHWD MM4, MM0 + + PAddD MM4, [SI+8] + MovQ MM5, MM3 + + MovQM [SI], MM2 + PUnpckLWD MM3, MM1 + + MovQM [SI+8], MM4 + PUnpckHWD MM5, MM1 + + PAddD MM3, [SI+10h] + PAddD MM5, [SI+18h] + + MovQM [SI+10h], MM3 + MovQM [SI+18h], MM5 + +M32Bit16MPannedEnd: +IF MONITORPERFORMANCE + RdTSC + Add CS:M32BitMCounter16BitTicksLow, EAX + AdC CS:M32BitMCounter16BitTicksHigh, EDX +ENDIF + Ret + +EndP M32Bit16MPanned + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc M32Bit8MPanned + +; AX = number to mix +; CX = error +; DX = deltaoffset +; BP = deltaerror +; DS:SI = 32-bit output buffer +; ES:DI = sample location +; MM6 = L/R volumes +; MM7 = PXor mask + +IF MONITORPERFORMANCE + Push EAX + Push EDX + + Add CS:M32BitMCounter8BitLow, AX + AdC CS:M32BitMCounter8BitHigh, 0 + + RdTSC + Sub CS:M32BitMCounter8BitTicksLow, EAX + SBB CS:M32BitMCounter8BitTicksHigh, EDX + + Pop EDX + Pop EAX +ENDIF + + Mov BX, AX + And AX, 3 + JZ M32Bit8MPanned3 + +M32Bit8MPanned1: ; Mix 1 sample + Test AL, 1 + JZ M32Bit8MPanned2 + + Xor AX, AX + Add ERROR, DELTAERROR + Mov AH, [ES:DI] + AdC DI, DELTAOFFSET + Mov [DS:0], AX + + MovQ MM0, [DS:0] + PUnpckLWD MM0, MM0 + MovQ MM2, MM6 + PMulLW MM2, MM0 + PMulHW MM0, MM6 + PUnpckLWD MM2, MM0 + PAddD MM2, [SI] + MovQM [SI], MM2 + + Add SI, 8 + +M32Bit8MPanned2: ; Mix 2 samples + Test BL, 2 + JZ M32Bit8MPanned3 + + Xor AX, AX + + Mov AH, [ES:DI] + Add ERROR, DELTAERROR + AdC DI, DELTAOFFSET + Mov [DS:0], AX + + Mov AH, [ES:DI] + Add ERROR, DELTAERROR + AdC DI, DELTAOFFSET + Mov [DS:2], AX + + MovQ MM0, [DS:0] + PUnpckLWD MM0, MM0 + MovQ MM2, MM6 + PMulLW MM2, MM0 + PMulHW MM0, MM6 + MovQ MM4, MM2 + PUnpckLWD MM2, MM0 + PUnpckHWD MM4, MM0 + PAddD MM2, [SI] + PAddD MM4, [SI+8] + MovQM [SI], MM2 + MovQM [SI+8], MM4 + + Add SI, 10h + +M32Bit8MPanned3: + Xor AX, AX + ShR BX, 2 + JZ M32Bit8MPannedEnd + + Mov AH, [ES:DI] + Add ERROR, DELTAERROR + AdC DI, DELTAOFFSET + Mov [DS:0], AX + + Mov AH, [ES:DI] + Add ERROR, DELTAERROR + AdC DI, DELTAOFFSET + Mov [DS:2], AX + + Mov AH, [ES:DI] + Add ERROR, DELTAERROR + AdC DI, DELTAOFFSET + Mov [DS:0Ch], AX + + Mov AH, [ES:DI] + Add ERROR, DELTAERROR + AdC DI, DELTAOFFSET + Mov [DS:0Eh], AX + + Dec BX + JZ M32Bit8MPanned5 + +M32Bit8MPanned4: + MovQ MM0, [DS:0] + MovQ MM2, MM6 + MovQ MM1, [DS:8] + PUnpckLWD MM0, MM0 + + PMulLW MM2, MM0 + PUnpckHWD MM1, MM1 + + PMulHW MM0, MM6 + MovQ MM3, MM6 + + Mov AH, [ES:DI] + Add ERROR, DELTAERROR + AdC DI, DELTAOFFSET + Mov [DS:0], AX + + MovQ MM4, MM2 + PUnpckLWD MM2, MM0 + + PAddD MM2, [SI] + PUnpckHWD MM4, MM0 + + PAddD MM4, [SI+8] + PMulLW MM3, MM1 + + MovQM [SI], MM2 + PMulHW MM1, MM6 + + Mov AH, [ES:DI] + Add ERROR, DELTAERROR + AdC DI, DELTAOFFSET + Mov [DS:2], AX + + MovQM [SI+8], MM4 + MovQ MM5, MM3 + + MovQ MM0, [SI+18h] + PUnpckLWD MM3, MM1 + PAddD MM3, [SI+10h] + PUnpckHWD MM5, MM1 + MovQM [SI+10h], MM3 + PAddD MM5, MM0 + + Mov AH, [ES:DI] + Add ERROR, DELTAERROR + AdC DI, DELTAOFFSET + Mov [DS:0Ch], AX + + MovQM [SI+18h], MM5 + + Mov AH, [ES:DI] + Add ERROR, DELTAERROR + AdC DI, DELTAOFFSET + Mov [DS:0Eh], AX + + Add SI, 20h + + Dec BX + JNZ M32Bit8MPanned4 + +M32Bit8MPanned5: + MovQ MM0, [DS:0] + MovQ MM2, MM6 + + MovQ MM1, [DS:8] + PUnpckLWD MM0, MM0 + + PMulLW MM2, MM0 + MovQ MM3, MM6 + + PMulHW MM0, MM6 + PUnpckHWD MM1, MM1 + + MovQ MM4, MM2 + PMulLW MM3, MM1 + + PUnpckLWD MM2, MM0 + PMulHW MM1, MM6 + + PAddD MM2, [SI] + PUnpckHWD MM4, MM0 + + PAddD MM4, [SI+8] + MovQ MM5, MM3 + + MovQM [SI], MM2 + PUnpckLWD MM3, MM1 + + MovQM [SI+8], MM4 + PUnpckHWD MM5, MM1 + + PAddD MM3, [SI+10h] + PAddD MM5, [SI+18h] + + MovQM [SI+10h], MM3 + MovQM [SI+18h], MM5 + +M32Bit8MPannedEnd: +IF MONITORPERFORMANCE + RdTSC + Add CS:M32BitMCounter8BitTicksLow, EAX + AdC CS:M32BitMCounter8BitTicksHigh, EDX +ENDIF + Ret + +EndP M32Bit8MPanned + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreM32BitMPanned + Assume DS:Driver + + Mov EAX, [SI+0Ch] ; LEAX = left vol, HEAX = right vol + Mov [DWord Ptr CS:M32BitMVolumeData], EAX + Mov [DWord Ptr CS:M32BitMVolumeData+4], EAX + + SegCS MovQ MM6, M32BitMVolumeData + + Ret + +EndP PreM32BitMPanned + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + diff --git a/SoundDrivers/M32BITMF.INC b/SoundDrivers/M32BITMF.INC new file mode 100755 index 0000000..3f83cf2 --- /dev/null +++ b/SoundDrivers/M32BITMF.INC @@ -0,0 +1,12 @@ +; 8 bit tables + + DW Offset MixNoLoop, PreM32BitMFPanned, MFS8Bit, MBS8Bit, M32Bit8MFPanned + DW Offset MixForwardsLoop, PreM32BitMFPanned, MFS8Bit, MBS8Bit, M32Bit8MFPanned + DW Offset MixPingPongLoop, PreM32BitMFPanned, MFS8Bit, MBS8Bit, M32Bit8MFPanned + +; 16 bit tables + + DW Offset MixNoLoop, PreM32BitMFPanned, MFS16Bit, MBS16Bit, M32Bit16MFPanned + DW Offset MixForwardsLoop, PreM32BitMFPanned, MFS16Bit, MBS16Bit, M32Bit16MFPanned + DW Offset MixPingPongLoop, PreM32BitMFPanned, MFS16Bit, MBS16Bit, M32Bit16MFPanned + diff --git a/SoundDrivers/M32BITMF.MIX b/SoundDrivers/M32BITMF.MIX new file mode 100755 index 0000000..e3bb9c3 --- /dev/null +++ b/SoundDrivers/M32BITMF.MIX @@ -0,0 +1,708 @@ + +; +; Resonant filter mixing routines +; + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MONITORPERFORMANCE = 0 +RAMPSPEED = 7 +RAMPCOMPENSATE = 63 + +IF MONITORPERFORMANCE +ALIGN 16 +M32BitMICounter8BitTicksLow DD 0 +M32BitMICounter8BitTicksHigh DD 0 +M32BitMICounter16BitTicksLow DD 0 +M32BitMICounter16BitTicksHigh DD 0 +M32BitMICounter8BitLow DW 0 +M32BitMICounter8BitHigh DW 0 +M32BitMICounter16BitLow DW 0 +M32BitMICounter16BitHigh DW 0 +ENDIF + + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc M32Bit16MFPanned + +; AX = number to mix +; CX = error +; DX = deltaoffset +; BP = deltaerror +; DS:SI = 32-bit output buffer +; ES:EDI+EDI = sample location +; MM6 = L/R volumes +; MM7 = PXor mask + +IF MONITORPERFORMANCE + Push EAX + Push EDX + + Add CS:M32BitMICounter16BitLow, AX + AdC CS:M32BitMICounter16BitHigh, 0 + + RdTSC + Sub CS:M32BitMICounter16BitTicksLow, EAX + SBB CS:M32BitMICounter16BitTicksHigh, EDX + + Pop EDX + Pop EAX +ENDIF + +; 16 bit code here + Assume DS:Driver + SegCS MovQ MM2, M32BitMIPNotMask ; = FFFF0000FFFF0000h + Assume DS:Nothing + + Test AX, 1 + JZ M32Bit16MFPanned1 + + Push AX + MovD MM1, CX + + Mov EBX, [ES:EDI+EDI] + Add CX, BP + AdC DI, DX + PUnpckLWD MM1, MM1 + + MovD MM0, BX + PXor MM1, MM2 + + MovQ MM3, [DS:10h] + PSRLWI MM1, 1 + + PMAddWD MM0, MM1 + PMAddWD MM3, [DS:8] + + PSRADI MM0, 16 + MovQ MM1, MM3 + + PMAddWD MM0, [DS:0] + PSRLQI MM3, 32 + + PAddD MM3, MM1 + PAddD MM0, MM3 + PSRADI MM0, 14 + PUnpckLDQ MM0, MM0 + PackSSDW MM0, MM0 + + MovDR AX, MM0 + MovQ MM1, MM6 + PMulLW MM1, MM0 + PMulHW MM0, MM6 + + Mov BX, [DS:10h] + Mov [DS:10h], AX + Mov [DS:14h], BX + + MovQ MM3, [DS:18h] ; VR + PUnpckLWD MM1, MM0 + PSubW MM3, MM6 ; VR + PAddD MM1, [SI] + PSRAWI MM3, RAMPSPEED ; VR + MovQM [SI], MM1 + PAddW MM6, MM3 ; VR + + Add SI, 8 + Pop AX + +M32Bit16MFPanned1: + ShR AX, 1 + JZ M32Bit16MFPannedEnd + + Mov [DS:38h], CX + Mov EBX, [ES:EDI+EDI] + Mov [DS:3Ah], CX + Add CX, BP + AdC DI, DX + Mov [DS:30h], EBX + + Mov [DS:3Ch], CX + Mov EBX, [ES:EDI+EDI] + Mov [DS:3Eh], CX + Add CX, BP + AdC DI, DX + Mov [DS:34h], EBX + + MovQ MM5, [DS:38h] + + Mov [DS:38h], BP + Mov [DS:3Ch], BP + Mov [DS:3Ah], BP + Mov [DS:3Eh], BP + + MovQ MM7, [DS:38h] + PXor MM5, MM2 ; MM5 = offsets. + PAddW MM7, MM7 + PXor MM7, MM2 + PSubW MM7, MM2 ; MM7 = offset step + + Dec AX + JZ M32Bit16MFPanned3 + + Mov [DS:20h], AX + +M32Bit16MFPanned2: + MovQ MM2, [DS:10h] + MovQ MM0, MM5 + + PMAddWD MM2, [DS:8] + PSRLWI MM0, 1 + + PMAddWD MM0, [DS:30h] + PAddW MM5, MM7 + + PSRADI MM0, 16 + MovQ MM1, MM2 + + PMAddWD MM0, [DS:0] + PSRLQI MM2, 32 + + Mov EBX, [ES:EDI+EDI] + Add CX, BP + AdC DI, DX + Mov [DS:30h], EBX + + PAddD MM2, MM1 + MovQ MM3, MM0 + + PAddD MM0, MM2 + + PSRADI MM0, 14 + + MovQ MM1, MM0 + PackSSDW MM0, MM0 + + MovDR AX, MM0 + + Mov BX, [DS:10h] + Mov [DS:14h], BX + Mov [DS:10h], AX + + MovQ MM2, [DS:8] + PUnpckLDQ MM1, MM1 + + PMAddWD MM2, [DS:10h] + + Mov EBX, [ES:EDI+EDI] + Add CX, BP + AdC DI, DX + Mov [DS:34h], EBX + + PAddD MM3, MM2 + PSLLQI MM2, 32 + + PAddD MM3, MM2 ; MM3 = FS2, x + + PSRADI MM3, 14 + + PUnpckHDQ MM3, MM3 + MovQ MM0, MM6 + + PackSSDW MM3, MM1 ; MM3 = FS1, FS1, FS2, FS2 + + PMulLW MM0, MM3 + + MovDR AX, MM3 + PMulHW MM3, MM6 + + MovQ MM1, MM0 + + MovQ MM2, [DS:18h] ; VR + PUnpckHWD MM0, MM3 + + PAddD MM0, [SI] + PUnpckLWD MM1, MM3 + + PAddD MM1, [SI+8] + PSubW MM2, MM6 ; VR + + MovQM [SI], MM0 + PSRAWI MM2, RAMPSPEED-1 ; VR + + MovQM [SI+8], MM1 + PAddW MM6, MM2 ; VR + + Mov BX, [DS:10h] + Add SI, 10h + Mov [DS:10h], AX + Mov [DS:14h], BX + + Dec Word Ptr [DS:20h] + JNZ M32Bit16MFPanned2 + +M32Bit16MFPanned3: + MovQ MM0, [DS:30h] + PSRLWI MM5, 1 + + MovQ MM2, [DS:10h] + + PMAddWD MM0, MM5 + PMAddWD MM2, [DS:8] + + PSRADI MM0, 16 + MovQ MM1, MM2 + + PMAddWD MM0, [DS:0] + PSRLQI MM2, 32 + + PAddD MM2, MM1 + MovQ MM3, MM0 + + PAddD MM0, MM2 + + PSRADI MM0, 14 + + MovQ MM1, MM0 + PackSSDW MM0, MM0 + MovDR AX, MM0 + + Mov BX, [DS:10h] + Mov [DS:10h], AX + Mov [DS:14h], BX + + MovQ MM2, [DS:8] + PUnpckLDQ MM1, MM1 + + PMAddWD MM2, [DS:10h] + + PAddD MM3, MM2 + PSLLQI MM2, 32 + + PAddD MM3, MM2 ; MM3 = FS2, x + + PSRADI MM3, 14 + + PUnpckHDQ MM3, MM3 + MovQ MM0, MM6 + + PackSSDW MM3, MM1 ; MM3 = FS1, FS1, FS2, FS2 + + PMulLW MM0, MM3 + + MovDR AX, MM3 + PMulHW MM3, MM6 + + MovQ MM1, MM0 + + MovQ MM2, [DS:18h] ; VR + PUnpckHWD MM0, MM3 + + PAddD MM0, [SI] + PUnpckLWD MM1, MM3 + + PAddD MM1, [SI+8] + PSubW MM2, MM6 ; VR + + MovQM [SI], MM0 + PSRAWI MM2, RAMPSPEED-1 ; VR + + MovQM [SI+8], MM1 + PAddW MM6, MM2 ; VR + + Mov BX, [DS:10h] + Add SI, 10h + Mov [DS:10h], AX + Mov [DS:14h], BX + +M32Bit16MFPannedEnd: +IF MONITORPERFORMANCE + RdTSC + Add CS:M32BitMICounter16BitTicksLow, EAX + AdC CS:M32BitMICounter16BitTicksHigh, EDX +ENDIF + Ret + +EndP M32Bit16MFPanned + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc M32Bit8MFPanned + +; Layout of data in data segment +; DS:0 = destination volume +; DS:10h->1Fh = samples +; DS:20h = SS, SP storage + +; AX = number to mix +; CX = error +; DX = deltaoffset +; BP = deltaerror +; DS:SI = 32-bit output buffer +; ES:DI = sample location +; MM6 = L/R volumes +; MM7 = PXor mask + +IF MONITORPERFORMANCE + Push EAX + Push EDX + + Add CS:M32BitMICounter8BitLow, AX + AdC CS:M32BitMICounter8BitHigh, 0 + + RdTSC + Sub CS:M32BitMICounter8BitTicksLow, EAX + SBB CS:M32BitMICounter8BitTicksHigh, EDX + + Pop EDX + Pop EAX +ENDIF + +; AX = number of samples to mix. +; MM6 = current volume. +; DS:0 = filtera +; DS:8 = filterb, filterc +; DS:10h = oldsamples. +; DS:18h = destination volume. +; DS:20h = Count +; DS:24h = ... +; DS:30h = sample area, 38h = offset area + + Assume DS:Driver + SegCS MovQ MM2, M32BitMIPNotMask ; = FFFF0000FFFF0000h + Assume DS:Nothing + + Test AX, 1 + JZ M32Bit8MFPanned1 + + MovD MM1, CX + Push AX + + Mov BX, [ES:DI] + Add CX, BP + AdC DI, DX + + MovD MM0, BX + PUnpckLWD MM1, MM1 + + PUnpckLBW MM0, MM0 + PXor MM1, MM2 + + MovQ MM3, [DS:10h] + PSRLWI MM1, 1 + + PMAddWD MM0, MM1 + PMAddWD MM3, [DS:8] + + PSRADI MM0, 16 + MovQ MM1, MM3 + + PMAddWD MM0, [DS:0] + PSRLQI MM3, 32 + + PAddD MM3, MM1 + PAddD MM0, MM3 + PSRADI MM0, 14 + PUnpckLDQ MM0, MM0 + PackSSDW MM0, MM0 + + MovDR AX, MM0 + MovQ MM1, MM6 + PMulLW MM1, MM0 + PMulHW MM0, MM6 + + Mov BX, [DS:10h] + Mov [DS:14h], BX + Mov [DS:10h], AX + + MovQ MM3, [DS:18h] ; VR + PUnpckLWD MM1, MM0 + PSubW MM3, MM6 ; VR + PAddD MM1, [SI] + PSRAWI MM3, RAMPSPEED ; VR + MovQM [SI], MM1 + PAddW MM6, MM3 ; VR + + Pop AX + Add SI, 8 + +M32Bit8MFPanned1: + ShR AX, 1 + JZ M32Bit8MFPannedEnd + + Mov [DS:38h], CX + Mov BX, [ES:DI] + Mov [DS:3Ah], CX + Add CX, BP + AdC DI, DX + Mov [DS:30h], BX + + Mov [DS:3Ch], CX + Mov BX, [ES:DI] + Mov [DS:3Eh], CX + Add CX, BP + AdC DI, DX + Mov [DS:32h], BX + + MovD MM7, BP + MovQ MM5, [DS:38h] + PUnpckLWD MM7, MM7 + PXor MM5, MM2 ; MM5 = offsets. + PUnpckLDQ MM7, MM7 + PAddW MM7, MM7 + PXor MM7, MM2 + PSubW MM7, MM2 ; MM7 = offset step + + Dec AX + JZ M32Bit8MFPanned3 + + Mov [DS:20h], AX + +M32Bit8MFPanned2: + MovD MM0, [DS:30h] + MovQ MM1, MM5 + + PUnpckLBW MM0, MM0 + PSRLWI MM1, 1 + + MovQ MM2, [DS:10h] + PMAddWD MM0, MM1 + + PMAddWD MM2, [DS:8] + PAddW MM5, MM7 + + MovQ MM1, MM2 + PSRADI MM0, 16 + + PMAddWD MM0, [DS:0] + PSRLQI MM2, 32 + + Mov BX, [ES:DI] + Add CX, BP + AdC DI, DX + Mov [DS:30h], BX + + PAddD MM2, MM1 + MovQ MM3, MM0 + + PAddD MM0, MM2 + + PSRADI MM0, 14 + + MovQ MM1, MM0 + PackSSDW MM0, MM0 + + MovDR AX, MM0 + + Mov BX, [DS:10h] + Mov [DS:10h], AX + Mov [DS:14h], BX + + MovQ MM2, [DS:8] + PUnpckLDQ MM1, MM1 + + PMAddWD MM2, [DS:10h] + + Mov BX, [ES:DI] + Add CX, BP + AdC DI, DX + Mov [DS:32h], BX + + PAddD MM3, MM2 + PSLLQI MM2, 32 + + PAddD MM3, MM2 ; MM3 = FS2, x + + PSRADI MM3, 14 + + PUnpckHDQ MM3, MM3 + MovQ MM0, MM6 + + PackSSDW MM3, MM1 ; MM3 = FS1, FS1, FS2, FS2 + + PMulLW MM0, MM3 + + MovDR AX, MM3 + PMulHW MM3, MM6 + + MovQ MM1, MM0 + + MovQ MM2, [DS:18h] ; VR + PUnpckHWD MM0, MM3 + + PAddD MM0, [SI] + PUnpckLWD MM1, MM3 + + PAddD MM1, [SI+8] + PSubW MM2, MM6 ; VR + + MovQM [SI], MM0 + PSRAWI MM2, RAMPSPEED-1 ; VR + + MovQM [SI+8], MM1 + PAddW MM6, MM2 ; VR + + Mov BX, [DS:10h] + Add SI, 10h + Mov [DS:10h], AX + Mov [DS:14h], BX + + Dec Word Ptr [DS:20h] + JNZ M32Bit8MFPanned2 + +M32Bit8MFPanned3: + MovD MM0, [DS:30h] + PSRLWI MM5, 1 + + MovQ MM2, [DS:10h] + PUnpckLBW MM0, MM0 + + PMAddWD MM0, MM5 + PMAddWD MM2, [DS:8] + + PSRADI MM0, 16 + MovQ MM1, MM2 + + PMAddWD MM0, [DS:0] + PSRLQI MM2, 32 + + PAddD MM2, MM1 + MovQ MM3, MM0 + + PAddD MM0, MM2 + + PSRADI MM0, 14 + + MovQ MM1, MM0 + PackSSDW MM0, MM0 + MovDR AX, MM0 + + Mov BX, [DS:10h] + Mov [DS:14h], BX + Mov [DS:10h], AX + + MovQ MM2, [DS:8] + PUnpckLDQ MM1, MM1 + + PMAddWD MM2, [DS:10h] + + PAddD MM3, MM2 + PSLLQI MM2, 32 + + PAddD MM3, MM2 ; MM3 = FS2, x + + PSRADI MM3, 14 + + PUnpckHDQ MM3, MM3 + MovQ MM0, MM6 + + PackSSDW MM3, MM1 ; MM3 = FS1, FS1, FS2, FS2 + + PMulLW MM0, MM3 + + MovDR AX, MM3 + PMulHW MM3, MM6 + + MovQ MM1, MM0 + + MovQ MM2, [DS:18h] ; VR + PUnpckHWD MM0, MM3 + + PAddD MM0, [SI] + PUnpckLWD MM1, MM3 + + PAddD MM1, [SI+8] + PSubW MM2, MM6 ; VR + + MovQM [SI], MM0 + PSRAWI MM2, RAMPSPEED-1 ; VR + + MovQM [SI+8], MM1 + PAddW MM6, MM2 ; VR + + Mov BX, [DS:10h] + Add SI, 10h + Mov [DS:10h], AX + Mov [DS:14h], BX + +M32Bit8MFPannedEnd: +IF MONITORPERFORMANCE + RdTSC + Add CS:M32BitMICounter8BitTicksLow, EAX + AdC CS:M32BitMICounter8BitTicksHigh, EDX +ENDIF + Ret + +EndP M32Bit8MFPanned + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreM32BitMFPanned + Assume DS:Driver + + Mov ES, CS:MixSegment + + Mov AX, [SI+0Ch] ; AX = destination left + Mov BX, [SI+1Ch] ; BX = current left + Mov CX, [SI+0Eh] ; CX = destination right + Mov DX, [SI+1Eh] ; DX = current right. + + Test Word Ptr [SI], 8540h + JZ PreM32BitMFPannedV4 + + Add CX, CX + Add AX, AX + +PreM32BitMFPannedV4: + Test AX, AX + JNZ PreM32BitMFPannedV3 + Test CX, CX + JNZ PreM32BitMFPannedV3 + + Add Word Ptr [SI+8], 60 + +PreM32BitMFPannedV3: + Cmp AX, BX + JL PreM32BitMFPannedV1 + + Add AX, RAMPCOMPENSATE + +PreM32BitMFPannedV1: + Cmp CX, DX + JL PreM32BitMFPannedV2 + + Add CX, RAMPCOMPENSATE + +PreM32BitMFPannedV2: + Mov [ES:18h], AX + Mov [ES:1Ch], AX + Mov [ES:1Ah], CX + Mov [ES:1Eh], CX ; MixSegment:18h = destination volume + + Mov [CS:M32BitMIVolumeData], BX + Mov [CS:M32BitMIVolumeData+2], DX + Sub AX, BX + Sub CX, DX + SAR AX, RAMPSPEED + SAR CX, RAMPSPEED + Add BX, AX + Add DX, CX + Mov [CS:M32BitMIVolumeData+4], BX + Mov [CS:M32BitMIVolumeData+6], DX + SegCS MovQ MM6, M32BitMIVolumeData ; MM6 = current volume + + Xor EAX, EAX + Mov AX, [SI+5Eh] + Sub AX, 1 + AdC AX, 1 + Mov [ES:0], EAX + Mov [ES:4], EAX ; MixSegment:0 = filtera + + Mov AX, [SI+6Eh] + Mov [ES:8], EAX + Mov AX, [SI+7Eh] + Mov [ES:0Ch], EAX ; MixSegment:8 = filterb, filterc + + Mov AX, [SI+3Ch] + Mov [ES:10h], EAX + Mov AX, [SI+6] + Mov [ES:14h], EAX ; MixSegment:10h = old samples. + + Ret + +EndP PreM32BitMFPanned + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + diff --git a/SoundDrivers/M32BITMI.INC b/SoundDrivers/M32BITMI.INC new file mode 100755 index 0000000..799880e --- /dev/null +++ b/SoundDrivers/M32BITMI.INC @@ -0,0 +1,11 @@ +; 8 bit tables + + DW Offset MixNoLoop, PreM32BitMIPanned, MFS8Bit, MBS8Bit, M32Bit8MIPanned + DW Offset MixForwardsLoop, PreM32BitMIPanned, MFS8Bit, MBS8Bit, M32Bit8MIPanned + DW Offset MixPingPongLoop, PreM32BitMIPanned, MFS8Bit, MBS8Bit, M32Bit8MIPanned + +; 16 bit tables + DW Offset MixNoLoop, PreM32BitMIPanned, MFS16Bit, MBS16Bit, M32Bit16MIPanned + DW Offset MixForwardsLoop, PreM32BitMIPanned, MFS16Bit, MBS16Bit, M32Bit16MIPanned + DW Offset MixPingPongLoop, PreM32BitMIPanned, MFS16Bit, MBS16Bit, M32Bit16MIPanned + diff --git a/SoundDrivers/M32BITMI.MIX b/SoundDrivers/M32BITMI.MIX new file mode 100755 index 0000000..3bf0fde --- /dev/null +++ b/SoundDrivers/M32BITMI.MIX @@ -0,0 +1,686 @@ + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MONITORPERFORMANCE = 0 + +ALIGN 16 + +M32BitMIVolumeData DW 0, 0, 0, 0 +M32BitMIPXorMask DW 07FFFh, 0, 07FFFh, 0 +M32BitMIPNotMask DW 0FFFFh, 0, 0FFFFh, 0 + +IF MONITORPERFORMANCE +M32BitMICounter8BitTicksLow DD 0 +M32BitMICounter8BitTicksHigh DD 0 +M32BitMICounter16BitTicksLow DD 0 +M32BitMICounter16BitTicksHigh DD 0 +M32BitMICounter8BitLow DW 0 +M32BitMICounter8BitHigh DW 0 +M32BitMICounter16BitLow DW 0 +M32BitMICounter16BitHigh DW 0 +ENDIF + + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc M32Bit16MIPanned + +; AX = number to mix +; CX = error +; DX = deltaoffset +; BP = deltaerror +; DS:SI = 32-bit output buffer +; ES:EDI+EDI = sample location +; MM6 = L/R volumes +; MM7 = PXor mask + +IF MONITORPERFORMANCE + Push EAX + Push EDX + + Add CS:M32BitMICounter16BitLow, AX + AdC CS:M32BitMICounter16BitHigh, 0 + + RdTSC + Sub CS:M32BitMICounter16BitTicksLow, EAX + SBB CS:M32BitMICounter16BitTicksHigh, EDX + + Pop EDX + Pop EAX +ENDIF + + Mov BX, DI + Add BX, BX + + Assume DS:Driver + SegCS MovQ MM3, M32BitMIPXorMask + Assume DS:Nothing + +M32Bit16MIPanned1: + Test AL, 1 + JZ M32Bit16MIPanned2 + + Push AX + Mov [DS:10h], CX + Mov AX, [ES:BX] + Mov [DS:12h], CX + Add CX, BP + AdC DI, DX + Mov [DS:0], AX + Mov AX, [ES:BX+2] + Mov BX, DI + Mov [DS:2], AX + Add BX, BX + + MovQ MM4, [DS:10h] + MovQ MM2, MM6 + MovQ MM0, [DS:0] + PSRLWI MM4, 1 + PXor MM4, MM3 + PMAddWD MM0, MM4 + PSRADI MM0, 15 + PUnpckLWD MM0, MM0 + PMulLW MM2, MM0 + PMulHW MM0, MM6 + PUnpckLWD MM2, MM0 + PAddD MM2, [SI] + MovQM [SI], MM2 + + Add SI, 8 + Pop AX + +M32Bit16MIPanned2: + Test AL, 2 + JZ M32Bit16MIPanned3 + + Push AX + Mov [DS:10h], CX + Mov AX, [ES:BX] + Mov [DS:12h], CX + Add CX, BP + AdC DI, DX + Mov [DS:0], AX + Mov AX, [ES:BX+2] + Mov BX, DI + Mov [DS:2], AX + Add BX, BX + + Mov [DS:14h], CX + Mov AX, [ES:BX] + Mov [DS:16h], CX + Add CX, BP + AdC DI, DX + Mov [DS:4], AX + Mov AX, [ES:BX+2] + Mov BX, DI + Mov [DS:6], AX + Add BX, BX + + MovQ MM4, [DS:10h] + MovQ MM2, MM6 + MovQ MM0, [DS:0] + PSRLWI MM4, 1 + + PXor MM4, MM3 + + PMAddWD MM0, MM4 + PSRADI MM0, 15 + PackSSDW MM0, MM0 + PUnpckLWD MM0, MM0 + PMulLW MM2, MM0 + PMulHW MM0, MM6 + MovQ MM4, MM2 + PUnpckLWD MM2, MM0 + PAddD MM2, [SI] + PUnpckHWD MM4, MM0 + PAddD MM4, [SI+8] + MovQM [SI], MM2 + MovQM [SI+8], MM4 + + Add SI, 10h + Pop AX + +M32Bit16MIPanned3: + ShR AX, 2 + JZ M32Bit16MIPannedEnd + + Mov [DS:20h], AX + + Mov [DS:10h], CX ; AGIs everywhere! + Mov AX, [ES:BX] + Mov [DS:12h], CX + Add CX, BP + AdC DI, DX + Mov [DS:0], AX + Mov AX, [ES:BX+2] + Mov BX, DI + Mov [DS:2], AX + Add BX, BX + + Mov [DS:14h], CX + Mov AX, [ES:BX] + Mov [DS:16h], CX + Add CX, BP + AdC DI, DX + Mov [DS:4], AX + Mov AX, [ES:BX+2] + Mov BX, DI + Mov [DS:6], AX + Add BX, BX + + MovQ MM5, [DS:10h] + + Mov [DS:10h], BP + Mov [DS:14h], BP + Add CX, BP + Mov AX, [ES:BX] + AdC DI, DX + Mov [DS:8], AX + Mov AX, [ES:BX+2] + Mov BX, DI + Mov [DS:0Ah], AX + Add BX, BX + + Mov [DS:12h], BP + Mov [DS:16h], BP + Add CX, BP + Mov AX, [ES:BX] + AdC DI, DX + Mov [DS:0Ch], AX + Mov AX, [ES:BX+2] + Mov BX, DI + Mov [DS:0Eh], AX + Add BX, BX + + Assume DS:Driver + SegCS MovQ MM4, M32BitMIPNotMask + Assume DS:Nothing + + MovQ MM7, [DS:10h] + PXor MM5, MM4 + + PAddW MM7, MM7 + MovQ MM2, MM5 + + PXor MM7, MM4 + PSRLWI MM2, 1 + + PSubW MM7, MM4 + PAddW MM5, MM7 + MovQ MM3, MM5 + + Dec Word Ptr [DS:20h] + JZ M32Bit16MIPanned5 + +M32Bit16MIPanned4: ; MM7 = delta offsets. + PMAddWD MM2, [DS:0] + PSRLWI MM3, 1 + +; Stall (2) + Add CX, BP + Mov AX, [ES:BX] + AdC DI, DX + Mov [DS:0], AX + Mov AX, [ES:BX+2] + Mov BX, DI + Mov [DS:2], AX + Add BX, BX + + PMAddWD MM3, [DS:8] + PSRADI MM2, 15 + + PackSSDW MM2, MM2 + PAddW MM5, MM7 + + PUnpckLWD MM2, MM2 + MovQ MM0, MM6 + + PMulHW MM0, MM2 + PSRADI MM3, 15 + + PMulLW MM2, MM6 + PackSSDW MM3, MM3 + + Add CX, BP + Mov AX, [ES:BX] + AdC DI, DX + Mov [DS:4], AX + Mov AX, [ES:BX+2] + Mov BX, DI + Mov [DS:6], AX + Add BX, BX + +; Stall (1) + MovQ MM4, MM2 + PUnpckLWD MM3, MM3 + + PUnpckLWD MM2, MM0 + MovQ MM1, MM6 + + PMulHW MM1, MM3 + PUnpckHWD MM4, MM0 + + PAddD MM2, [SI] + PMulLW MM3, MM6 + + Add CX, BP + Mov AX, [ES:BX] + AdC DI, DX + Mov [DS:8], AX + Mov AX, [ES:BX+2] + Mov BX, DI + Mov [DS:0Ah], AX + Add BX, BX + +; Stall (1) + PAddD MM4, [SI+8] + MovQ MM0, MM3 ; + + MovQM [SI], MM2 + PUnpckLWD MM3, MM1 + + MovQM [SI+8], MM4 + PUnpckHWD MM0, MM1 + + Add CX, BP + Mov AX, [ES:BX] + AdC DI, DX + Mov [DS:0Ch], AX + Mov AX, [ES:BX+2] + Mov BX, DI + Mov [DS:0Eh], AX + Add BX, BX + + PAddD MM3, [SI+10h] + MovQ MM2, MM5 + + PAddD MM0, [SI+18h] + PAddW MM5, MM7 + + MovQM [SI+10h], MM3 + MovQ MM3, MM5 + + MovQM [SI+18h], MM0 + PSRLWI MM2, 1 + + Add SI, 20h + Dec Word Ptr [DS:20h] + JNZ M32Bit16MIPanned4 + +M32Bit16MIPanned5: + PMAddWD MM2, [DS:0] + PSRLWI MM3, 1 + + PMAddWD MM3, [DS:8] + PSRADI MM2, 15 + + PackSSDW MM2, MM2 + PAddW MM5, MM7 + + PUnpckLWD MM2, MM2 + MovQ MM0, MM6 + + PMulHW MM0, MM2 + PSRADI MM3, 15 + + PMulLW MM2, MM6 + PackSSDW MM3, MM3 + + MovQ MM4, MM2 + PUnpckLWD MM3, MM3 + + PUnpckLWD MM2, MM0 + MovQ MM1, MM6 + + PMulHW MM1, MM3 + PUnpckHWD MM4, MM0 + + PAddD MM2, [SI] + PMulLW MM3, MM6 + + PAddD MM4, [SI+8] + MovQ MM0, MM3 + + MovQM [SI], MM2 + PUnpckLWD MM3, MM1 + + MovQM [SI+8], MM4 + PUnpckHWD MM0, MM1 + + PAddD MM3, [SI+10h] + PAddD MM0, [SI+18h] + MovQM [SI+10h], MM3 + MovQM [SI+18h], MM0 + +M32Bit16MIPannedEnd: +IF MONITORPERFORMANCE + RdTSC + Add CS:M32BitMICounter16BitTicksLow, EAX + AdC CS:M32BitMICounter16BitTicksHigh, EDX +ENDIF + Ret + +EndP M32Bit16MIPanned + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc M32Bit8MIPanned + +; AX = number to mix +; CX = error +; DX = deltaoffset +; BP = deltaerror +; DS:SI = 32-bit output buffer +; ES:DI = sample location +; MM6 = L/R volumes +; MM7 = PXor mask + +IF MONITORPERFORMANCE + Push EAX + Push EDX + + Add CS:M32BitMICounter8BitLow, AX + AdC CS:M32BitMICounter8BitHigh, 0 + + RdTSC + Sub CS:M32BitMICounter8BitTicksLow, EAX + SBB CS:M32BitMICounter8BitTicksHigh, EDX + + Pop EDX + Pop EAX +ENDIF + + Mov BX, AX + + And AX, 3 + JZ M32Bit8MIPanned3 + + Assume DS:Driver + SegCS MovQ MM3, M32BitMIPXorMask + Assume DS:Nothing + +M32Bit8MIPanned1: + Test AL, 1 + JZ M32Bit8MIPanned2 + + Mov AX, [ES:DI] + Mov [DS:10h], CX + Mov [DS:12h], CX + Add CX, BP + AdC DI, DX + + MovQ MM4, [DS:10h] + MovQ MM2, MM6 + MovD MM0, AX + PSRLWI MM4, 1 + PXor MM4, MM3 + PUnpckLBW MM0, MM0 + PMAddWD MM0, MM4 + PSRADI MM0, 15 + PUnpckLWD MM0, MM0 + PMulLW MM2, MM0 + PMulHW MM0, MM6 + PUnpckLWD MM2, MM0 + PAddD MM2, [SI] + MovQM [SI], MM2 + + Add SI, 8 + +M32Bit8MIPanned2: ; Mix 2 samples + Test BL, 2 + JZ M32Bit8MIPanned3 + + Mov AX, [ES:DI] + Mov [DS:10h], CX + Mov [DS:12h], CX + Add CX, BP + AdC DI, DX + Mov [DS:0], AX + + Mov AX, [ES:DI] + Mov [DS:14h], CX + Mov [DS:16h], CX + Add CX, BP + AdC DI, DX + Mov [DS:2], AX + + MovQ MM4, [DS:10h] + MovQ MM2, MM6 + MovQ MM0, [DS:0] + PSRLWI MM4, 1 + + PUnpckLBW MM0, MM0 + PXor MM4, MM3 + + PMAddWD MM0, MM4 + PSRADI MM0, 15 + PackSSDW MM0, MM0 + PUnpckLWD MM0, MM0 + PMulLW MM2, MM0 + PMulHW MM0, MM6 + MovQ MM4, MM2 + PUnpckLWD MM2, MM0 + PAddD MM2, [SI] + PUnpckHWD MM4, MM0 + PAddD MM4, [SI+8] + MovQM [SI], MM2 + MovQM [SI+8], MM4 + + Add SI, 10h + +M32Bit8MIPanned3: + ShR BX, 2 + JZ M32Bit8MIPannedEnd + +; Have to setup offset register and delta-offset register. + + Mov AX, [ES:DI] + Mov [DS:10h], ERROR + Mov [DS:12h], ERROR + Add ERROR, DELTAERROR + AdC DI, DELTAOFFSET + Mov [DS:0], AX + + Mov AX, [ES:DI] + Mov [DS:14h], ERROR + Mov [DS:16h], ERROR + Add ERROR, DELTAERROR + AdC DI, DELTAOFFSET + Mov [DS:2], AX + + Mov AX, [ES:DI] + Add ERROR, DELTAERROR + AdC DI, DELTAOFFSET + Mov [DS:18h], DELTAERROR + Mov [DS:8h], AX + Mov [DS:1Ah], DELTAERROR + + Mov AX, [ES:DI] + Add ERROR, DELTAERROR + AdC DI, DELTAOFFSET + Mov [DS:1Ch], DELTAERROR + Mov [DS:0Ah], AX + Mov [DS:1Eh], DELTAERROR + + Assume DS:Driver + SegCS MovQ MM4, M32BitMIPNotMask + Assume DS:Nothing + + MovQ MM7, [DS:18h] + MovQ MM5, [DS:10h] + + PAddW MM7, MM7 + + PXor MM7, MM4 + PXor MM5, MM4 + + PSubW MM7, MM4 + + Dec BX + JZ M32Bit8MIPanned5 + +M32Bit8MIPanned4: + MovQ MM0, [DS:0] + MovQ MM2, MM5 + + MovQ MM1, [DS:8] + PUnpckLBW MM0, MM0 + + PAddW MM5, MM7 + PSRLWI MM2, 1 + + PMAddWD MM0, MM2 + PUnpckLBW MM1, MM1 + + Mov AX, [ES:DI] + Add ERROR, DELTAERROR + AdC DI, DELTAOFFSET + Mov [DS:0], AX + + PSRADI MM0, 15 + MovQ MM3, MM5 + + PAddW MM5, MM7 + PSRLWI MM3, 1 + + PMAddWD MM1, MM3 + PackSSDW MM0, MM0 + + MovQ MM2, MM6 + PUnpckLWD MM0, MM0 + + Mov AX, [ES:DI] + Add ERROR, DELTAERROR + AdC DI, DELTAOFFSET + Mov [DS:2], AX + + PMulLW MM2, MM0 + PSRADI MM1, 15 + + PMulHW MM0, MM6 + PackSSDW MM1, MM1 + + Mov AX, [ES:DI] + Add ERROR, DELTAERROR + + MovQ MM4, MM2 + PUnpckLWD MM1, MM1 + + AdC DI, DELTAOFFSET + Mov [DS:8], AX + + MovQ MM3, MM6 + PUnpckLWD MM2, MM0 + + PAddD MM2, [SI] + PMulLW MM3, MM1 + + PMulHW MM1, MM6 + PUnpckHWD MM4, MM0 + + Mov AX, [ES:DI] + Add ERROR, DELTAERROR + AdC DI, DELTAOFFSET + Mov [DS:0Ah], AX + + PAddD MM4, [SI+8] + MovQ MM0, MM3 + + MovQM [SI], MM2 + PUnpckLWD MM3, MM1 + + MovQM [SI+8], MM4 + PUnpckHWD MM0, MM1 + + PAddD MM3, [SI+10h] + PAddD MM0, [SI+18h] + + MovQM [SI+10h], MM3 + MovQM [SI+18h], MM0 + + Add SI, 20h + + Dec BX + JNZ M32Bit8MIPanned4 + +M32Bit8MIPanned5: + MovQ MM0, [DS:0] + MovQ MM2, MM5 + MovQ MM1, [DS:8] + PUnpckLBW MM0, MM0 + PAddW MM5, MM7 + PSRLWI MM2, 1 + + PMAddWD MM0, MM2 + PUnpckLBW MM1, MM1 + + PSRLWI MM5, 1 + + PMAddWD MM1, MM5 + PSRADI MM0, 15 + + MovQ MM2, MM6 + PackSSDW MM0, MM0 + + MovQ MM3, MM6 + PUnpckLWD MM0, MM0 + + PMulLW MM2, MM0 + PSRADI MM1, 15 + + PMulHW MM0, MM6 + PackSSDW MM1, MM1 + + PUnpckLWD MM1, MM1 + MovQ MM4, MM2 + + PMulLW MM3, MM1 + PUnpckLWD MM2, MM0 + + PMulHW MM1, MM6 + PUnpckHWD MM4, MM0 + + PAddD MM2, [SI] + MovQ MM5, MM3 + + PAddD MM4, [SI+8] + PUnpckLWD MM3, MM1 + + MovQM [SI], MM2 + PUnpckHWD MM5, MM1 + + PAddD MM3, [SI+10h] + PAddD MM5, [SI+18h] + + MovQM [SI+8], MM4 + MovQM [SI+10h], MM3 + MovQM [SI+18h], MM5 + +M32Bit8MIPannedEnd: +IF MONITORPERFORMANCE + RdTSC + Add CS:M32BitMICounter8BitTicksLow, EAX + AdC CS:M32BitMICounter8BitTicksHigh, EDX +ENDIF + Ret + +EndP M32Bit8MIPanned + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreM32BitMIPanned + Assume DS:Driver + + Mov EAX, [SI+0Ch] ; LEAX = left vol, HEAX = right vol + Mov [DWord Ptr CS:M32BitMIVolumeData], EAX + Mov [DWord Ptr CS:M32BitMIVolumeData+4], EAX + + SegCS MovQ MM6, M32BitMIVolumeData + + Ret + +EndP PreM32BitMIPanned + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + diff --git a/SoundDrivers/M32BITMV.INC b/SoundDrivers/M32BITMV.INC new file mode 100755 index 0000000..2ae7a0f --- /dev/null +++ b/SoundDrivers/M32BITMV.INC @@ -0,0 +1,12 @@ +; 8 bit tables + + DW Offset MixNoLoop, PreM32BitMVPanned, MFS8Bit, MBS8Bit, M32Bit8MVPanned + DW Offset MixForwardsLoop, PreM32BitMVPanned, MFS8Bit, MBS8Bit, M32Bit8MVPanned + DW Offset MixPingPongLoop, PreM32BitMVPanned, MFS8Bit, MBS8Bit, M32Bit8MVPanned + +; 16 bit tables + + DW Offset MixNoLoop, PreM32BitMVPanned, MFS16Bit, MBS16Bit, M32Bit16MVPanned + DW Offset MixForwardsLoop, PreM32BitMVPanned, MFS16Bit, MBS16Bit, M32Bit16MVPanned + DW Offset MixPingPongLoop, PreM32BitMVPanned, MFS16Bit, MBS16Bit, M32Bit16MVPanned + diff --git a/SoundDrivers/M32BITMV.MIX b/SoundDrivers/M32BITMV.MIX new file mode 100755 index 0000000..2334538 --- /dev/null +++ b/SoundDrivers/M32BITMV.MIX @@ -0,0 +1,798 @@ + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MONITORPERFORMANCE = 0 +RAMPSPEED = 7 +RAMPCOMPENSATE = 63 + +IF MONITORPERFORMANCE +ALIGN 16 +M32BitMICounter8BitTicksLow DD 0 +M32BitMICounter8BitTicksHigh DD 0 +M32BitMICounter16BitTicksLow DD 0 +M32BitMICounter16BitTicksHigh DD 0 +M32BitMICounter8BitLow DW 0 +M32BitMICounter8BitHigh DW 0 +M32BitMICounter16BitLow DW 0 +M32BitMICounter16BitHigh DW 0 +ENDIF + + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc M32Bit16MVPanned + +; AX = number to mix +; CX = error +; DX = deltaoffset +; BP = deltaerror +; DS:SI = 32-bit output buffer +; ES:EDI+EDI = sample location +; MM6 = L/R volumes +; MM7 = PXor mask + +IF MONITORPERFORMANCE + Push EAX + Push EDX + + Add CS:M32BitMICounter16BitLow, AX + AdC CS:M32BitMICounter16BitHigh, 0 + + RdTSC + Sub CS:M32BitMICounter16BitTicksLow, EAX + SBB CS:M32BitMICounter16BitTicksHigh, EDX + + Pop EDX + Pop EAX +ENDIF + +; 16 bit code here + + Mov BX, DI + + Assume DS:Driver + SegCS MovQ MM1, M32BitMIPNotMask ; = FFFF0000FFFF0000h + Assume DS:Nothing + + Add BX, BX + + Test AL, 1 + JZ M32Bit16MVPanned2 + + Push AX + Mov [DS:8h], CX ; AGIs everywhere! + Mov AX, [ES:BX] + Mov [DS:0Ah], CX + Add CX, BP + AdC DI, DX + Mov [DS:10h], AX + Mov AX, [ES:BX+2] + Mov BX, DI + Mov [DS:12h], AX + Add BX, BX + + MovQ MM0, [DS:8h] + MovQ MM2, MM6 + PXor MM0, MM1 + PSRLWI MM0, 1 + PMAddWD MM0, [DS:10h] + PSRADI MM0, 15 + PUnpckLWD MM0, MM0 + PMulLW MM2, MM0 + MovQ MM4, [DS:0] ; VR + PMulHW MM0, MM6 + PSubW MM4, MM6 ; VR + PUnpckLWD MM2, MM0 + PAddD MM2, [SI] + PSRAWI MM4, RAMPSPEED ; VR + MovQM [SI], MM2 + PAddW MM6, MM4 ; VR + + Add SI, 8 + Pop AX + +M32Bit16MVPanned2: + Test AX, 2 + JZ M32Bit16MVPanned3 + + Push AX + Mov [DS:8h], CX ; AGIs everywhere! + Mov AX, [ES:BX] + Mov [DS:0Ah], CX + Add CX, BP + AdC DI, DX + Mov [DS:10h], AX + Mov AX, [ES:BX+2] + Mov BX, DI + Mov [DS:12h], AX + Add BX, BX + + Mov [DS:0Ch], CX + Mov AX, [ES:BX] + Mov [DS:0Eh], CX + Add CX, BP + AdC DI, DX + Mov [DS:14h], AX + Mov AX, [ES:BX+2] + Mov BX, DI + Mov [DS:16h], AX + Add BX, BX + + MovQ MM2, [DS:8] + PXor MM2, MM1 + PSRLWI MM2, 1 + PMAddWD MM2, [DS:10h] + PSRADI MM2, 15 + PackSSDW MM2, MM2 + PUnpckLWD MM2, MM2 + MovQ MM0, MM6 + PMulHW MM0, MM2 + PMulLW MM2, MM6 + MovQ MM4, MM2 + PUnpckLWD MM2, MM0 + MovQ MM5, [DS:0] ; VR + PUnpckHWD MM4, MM0 + PAddD MM2, [SI] + PSubW MM5, MM6 ; VR + PAddD MM4, [SI+8] + MovQM [SI], MM2 + PSRAWI MM5, RAMPSPEED-1 ; VR + MovQM [SI+8], MM4 + PAddW MM6, MM5 ; VR + + Pop AX + Add SI, 10h + +M32Bit16MVPanned3: + ShR AX, 2 + JZ M32Bit16MVPannedEnd + + Mov Word Ptr [DS:20h], AX + + Mov [DS:8h], CX ; AGIs everywhere! + Mov AX, [ES:BX] + Mov [DS:0Ah], CX + Add CX, BP + AdC DI, DX + Mov [DS:10h], AX + Mov AX, [ES:BX+2] + Mov BX, DI + Mov [DS:12h], AX + Add BX, BX + + Mov [DS:0Ch], CX + Mov AX, [ES:BX] + Mov [DS:0Eh], CX + Add CX, BP + AdC DI, DX + Mov [DS:14h], AX + Mov AX, [ES:BX+2] + Mov BX, DI + Mov [DS:16h], AX + Add BX, BX + + Mov [DS:28h], BP + Mov [DS:2Ch], BP + Add CX, BP + Mov AX, [ES:BX] + AdC DI, DX + Mov [DS:18h], AX + Mov AX, [ES:BX+2] + Mov BX, DI + Mov [DS:1Ah], AX + Add BX, BX + + Mov [DS:2Ah], BP + Mov [DS:2Eh], BP + Add CX, BP + Mov AX, [ES:BX] + AdC DI, DX + Mov [DS:1Ch], AX + Mov AX, [ES:BX+2] + Mov BX, DI + Mov [DS:1Eh], AX + Add BX, BX + + MovQ MM7, [DS:28h] + + MovQ MM5, [DS:8] + PAddW MM7, MM7 + + PXor MM7, MM1 + PXor MM5, MM1 + + PSubW MM7, MM1 + + Dec Word Ptr [DS:20h] + JZ M32Bit16MVPanned5 + +M32Bit16MVPanned4: +; DS:0 = destination volume +; DS:10h = samples +; DS:18h = samples +; MM5 = offsets +; MM6 = current volume +; MM7 = delta offsets + MovQ MM2, MM5 + PAddW MM5, MM7 + + PSRLWI MM2, 1 + MovQ MM3, MM5 + + PMAddWD MM2, [DS:10h] + PSRLWI MM3, 1 + + Add CX, BP + Mov AX, [ES:BX] + AdC DI, DX + Mov [DS:10h], AX + Mov AX, [ES:BX+2] + Mov BX, DI + Mov [DS:12h], AX + Add BX, BX + + PSRADI MM2, 15 + PAddW MM5, MM7 + + PMAddWD MM3, [DS:18h] + PackSSDW MM2, MM2 + + Add CX, BP + Mov AX, [ES:BX] + AdC DI, DX + Mov [DS:14h], AX + Mov AX, [ES:BX+2] + Mov BX, DI + Mov [DS:16h], AX + Add BX, BX + + PUnpckLWD MM2, MM2 + MovQ MM0, MM6 + + PMulHW MM0, MM2 + PSRADI MM3, 15 + + PMulLW MM2, MM6 + PackSSDW MM3, MM3 + + Add CX, BP + Mov AX, [ES:BX] + AdC DI, DX + Mov [DS:18h], AX + Mov AX, [ES:BX+2] + Mov BX, DI + Mov [DS:1Ah], AX + Add BX, BX + + MovQ MM1, [DS:0] ; Destination volume + PUnpckLWD MM3, MM3 + + MovQ MM4, MM2 + PUnpckLWD MM2, MM0 + + PSubW MM1, MM6 + PUnpckHWD MM4, MM0 + + PAddD MM2, [SI] + PSRAWI MM1, RAMPSPEED-1 + + PAddD MM4, [SI+8] + PAddW MM6, MM1 ; MM6 = new volume (ramped) + + MovQM [SI], MM2 + MovQ MM1, MM6 + + MovQ MM2, [DS:0] + PMulHW MM1, MM3 + + MovQM [SI+8], MM4 + PMulLW MM3, MM6 + + Add CX, BP + Mov AX, [ES:BX] + AdC DI, DX + Mov [DS:1Ch], AX + Mov AX, [ES:BX+2] + Mov BX, DI + Mov [DS:1Eh], AX + Add BX, BX + + MovQ MM0, MM3 + PUnpckLWD MM3, MM1 + + PAddD MM3, [SI+10h] + PUnpckHWD MM0, MM1 + + MovQM [SI+10h], MM3 + PSubW MM2, MM6 + + PAddD MM0, [SI+18h] + PSRAWI MM2, RAMPSPEED-1 + + MovQM [SI+18h], MM0 + PAddW MM6, MM2 + + Add SI, 20h + + Dec Word Ptr [DS:20h] + JNZ M32Bit16MVPanned4 + +M32Bit16MVPanned5: + MovQ MM2, MM5 + PAddW MM5, MM7 + + PSRLWI MM2, 1 + MovQ MM3, MM5 + + PMAddWD MM2, [DS:10h] + PSRLWI MM3, 1 + + PSRADI MM2, 15 + PAddW MM5, MM7 + + PMAddWD MM3, [DS:18h] + PackSSDW MM2, MM2 + + PUnpckLWD MM2, MM2 + MovQ MM0, MM6 + + PMulHW MM0, MM2 + PSRADI MM3, 15 + + PMulLW MM2, MM6 + PackSSDW MM3, MM3 + + MovQ MM1, [DS:0] ; Destination volume + PUnpckLWD MM3, MM3 + + MovQ MM4, MM2 + PUnpckLWD MM2, MM0 + + PSubW MM1, MM6 + PUnpckHWD MM4, MM0 + + PAddD MM2, [SI] + PSRAWI MM1, RAMPSPEED-1 + + PAddD MM4, [SI+8] + PAddW MM6, MM1 ; MM6 = new volume (ramped) + + MovQM [SI], MM2 + MovQ MM1, MM6 + + MovQ MM2, [DS:0] + PMulHW MM1, MM3 + + MovQM [SI+8], MM4 + PMulLW MM3, MM6 + + MovQ MM0, MM3 + PUnpckLWD MM3, MM1 + + PAddD MM3, [SI+10h] + PUnpckHWD MM0, MM1 + + MovQM [SI+10h], MM3 + PSubW MM2, MM6 + + PAddD MM0, [SI+18h] + PSRAWI MM2, RAMPSPEED-1 + + MovQM [SI+18h], MM0 + PAddW MM6, MM2 + +M32Bit16MVPannedEnd: + +IF MONITORPERFORMANCE + RdTSC + Add CS:M32BitMICounter16BitTicksLow, EAX + AdC CS:M32BitMICounter16BitTicksHigh, EDX +ENDIF + Ret + +EndP M32Bit16MVPanned + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc M32Bit8MVPanned + +; Layout of data in data segment +; DS:0 = destination volume +; DS:10h->1Fh = samples + +; AX = number to mix +; CX = error +; DX = deltaoffset +; BP = deltaerror +; DS:SI = 32-bit output buffer +; ES:DI = sample location +; MM6 = L/R volumes +; MM7 = PXor mask + +IF MONITORPERFORMANCE + Push EAX + Push EDX + + Add CS:M32BitMICounter8BitLow, AX + AdC CS:M32BitMICounter8BitHigh, 0 + + RdTSC + Sub CS:M32BitMICounter8BitTicksLow, EAX + SBB CS:M32BitMICounter8BitTicksHigh, EDX + + Pop EDX + Pop EAX +ENDIF + +; AX = number of samples to mix. +; DS:0 = destination volume +; DS:8 = SS +; DS:0Ch = SP +; DS:10h = sample setup +; MM6 = current volume. + + Mov BX, AX + + Assume DS:Driver + SegCS MovQ MM1, M32BitMIPNotMask ; = FFFF0000FFFF0000h + Assume DS:Nothing + + And AX, 3 + JZ M32Bit8MVPanned3 + +M32Bit8MVPanned1: + Test AL, 1 + JZ M32Bit8MVPanned2 + + Mov AX, [ES:DI] + Mov [DS:8h], CX + Mov [DS:0Ah], CX + Add CX, BP + AdC DI, DX + + MovQ MM4, [DS:8h] + MovQ MM2, MM6 + MovD MM0, AX + PXor MM4, MM1 + PSRLWI MM4, 1 + PUnpckLBW MM0, MM0 + PMAddWD MM0, MM4 + PSRADI MM0, 15 + PUnpckLWD MM0, MM0 + PMulLW MM2, MM0 + MovQ MM4, [DS:0] ; VR + PMulHW MM0, MM6 + PSubW MM4, MM6 ; VR + PUnpckLWD MM2, MM0 + PAddD MM2, [SI] + PSRAWI MM4, RAMPSPEED ; VR + MovQM [SI], MM2 + PAddW MM6, MM4 ; VR + + Add SI, 8 + +M32Bit8MVPanned2: + Test BL, 2 + JZ M32Bit8MVPanned3 + + Mov AX, [ES:DI] + Mov [DS:8h], CX + Mov [DS:0Ah], CX + Add CX, BP + AdC DI, DX + Mov [DS:10h], AX + + Mov AX, [ES:DI] + Mov [DS:0Ch], CX + Mov [DS:0Eh], CX + Add CX, BP + AdC DI, DX + Mov [DS:12h], AX + + MovQ MM0, [DS:10h] + MovQ MM2, [DS:8] + PXor MM2, MM1 + PUnpckLBW MM0, MM0 + PSRLWI MM2, 1 + PMAddWD MM2, MM0 + PSRADI MM2, 15 + PackSSDW MM2, MM2 + PUnpckLWD MM2, MM2 + MovQ MM0, MM6 + PMulHW MM0, MM2 + PMulLW MM2, MM6 + MovQ MM4, MM2 + PUnpckLWD MM2, MM0 + MovQ MM5, [DS:0] ; VR + PUnpckHWD MM4, MM0 + PAddD MM2, [SI] + PSubW MM5, MM6 ; VR + PAddD MM4, [SI+8] + MovQM [SI], MM2 + PSRAWI MM5, RAMPSPEED-1 ; VR + MovQM [SI+8], MM4 + PAddW MM6, MM5 ; VR + + Add SI, 10h + +M32Bit8MVPanned3: + ShR BX, 2 + JZ M32Bit8MVPannedEnd + + Mov AX, [ES:DI] + Mov [DS:8h], ERROR + Mov [DS:0Ah], ERROR + Add ERROR, BP + AdC DI, DELTAOFFSET + Mov [DS:10h], AX + + Mov AX, [ES:DI] + Mov [DS:0Ch], ERROR + Mov [DS:0Eh], ERROR + Add ERROR, BP + AdC DI, DELTAOFFSET + Mov [DS:12h], AX + + Mov AX, [ES:DI] + Add ERROR, BP + AdC DI, DELTAOFFSET + Mov [DS:28h], BP + Mov [DS:18h], AX + Mov [DS:2Ah], BP + + Mov AX, [ES:DI] + Add ERROR, BP + AdC DI, DELTAOFFSET + Mov [DS:2Ch], BP + Mov [DS:1Ah], AX + Mov [DS:2Eh], BP + + MovQ MM7, [DS:28h] + + MovQ MM5, [DS:8] + PAddW MM7, MM7 + + PXor MM7, MM1 + PXor MM5, MM1 + + PSubW MM7, MM1 + + Dec BX + JZ M32Bit8MVPanned5 + +M32Bit8MVPanned4: +; DS:0 = destination volume +; DS:10h = samples +; DS:18h = samples +; MM5 = offsets +; MM6 = current volume +; MM7 = delta offsets + MovQ MM0, [DS:10h] + MovQ MM2, MM5 + + MovQ MM1, [DS:18h] + PUnpckLBW MM0, MM0 + + PSRLWI MM2, 1 + PAddW MM5, MM7 + + PMAddWD MM2, MM0 + PUnpckLBW MM1, MM1 + + Mov AX, [ES:DI] + Add ERROR, DELTAERROR + AdC DI, DELTAOFFSET + Mov [DS:10h], AX + + PSRADI MM2, 15 + MovQ MM3, MM5 + + PAddW MM5, MM7 + PSRLWI MM3, 1 + + PMAddWD MM3, MM1 + PackSSDW MM2, MM2 + + Mov AX, [ES:DI] + Add ERROR, DELTAERROR + AdC DI, DELTAOFFSET + Mov [DS:12h], AX + + PUnpckLWD MM2, MM2 + MovQ MM0, MM6 + + PMulHW MM0, MM2 + PSRADI MM3, 15 + + PMulLW MM2, MM6 + PackSSDW MM3, MM3 + + Mov AX, [ES:DI] + Add ERROR, DELTAERROR + AdC DI, DELTAOFFSET + Mov [DS:18h], AX + + MovQ MM1, [DS:0] ; Destination volume + PUnpckLWD MM3, MM3 + + MovQ MM4, MM2 + PUnpckLWD MM2, MM0 + + PSubW MM1, MM6 + PUnpckHWD MM4, MM0 + + PAddD MM2, [SI] + PSRAWI MM1, RAMPSPEED-1 + + PAddD MM4, [SI+8] + PAddW MM6, MM1 ; MM6 = new volume (ramped) + + MovQM [SI], MM2 + MovQ MM1, MM6 + + MovQ MM2, [DS:0] + PMulHW MM1, MM3 + + MovQM [SI+8], MM4 + PMulLW MM3, MM6 + + Mov AX, [ES:DI] + Add ERROR, DELTAERROR + AdC DI, DELTAOFFSET + Mov [DS:1Ah], AX + + MovQ MM0, MM3 + PUnpckLWD MM3, MM1 + + PAddD MM3, [SI+10h] + PUnpckHWD MM0, MM1 + + MovQM [SI+10h], MM3 + PSubW MM2, MM6 + + PAddD MM0, [SI+18h] + PSRAWI MM2, RAMPSPEED-1 + + MovQM [SI+18h], MM0 + PAddW MM6, MM2 + + Add SI, 20h + + Dec BX + JNZ M32Bit8MVPanned4 + +M32Bit8MVPanned5: + MovQ MM0, [DS:10h] + MovQ MM2, MM5 + + MovQ MM1, [DS:18h] + PUnpckLBW MM0, MM0 + + PSRLWI MM2, 1 + PAddW MM5, MM7 + + PMAddWD MM2, MM0 + PUnpckLBW MM1, MM1 + + PSRADI MM2, 15 + MovQ MM3, MM5 + + PAddW MM5, MM7 + PSRLWI MM3, 1 + + PMAddWD MM3, MM1 + PackSSDW MM2, MM2 + + PUnpckLWD MM2, MM2 + MovQ MM0, MM6 + + PMulHW MM0, MM2 + PSRADI MM3, 15 + + PMulLW MM2, MM6 + PackSSDW MM3, MM3 + + MovQ MM1, [DS:0] ; Destination volume + PUnpckLWD MM3, MM3 + + MovQ MM4, MM2 + PUnpckLWD MM2, MM0 + + PSubW MM1, MM6 + PUnpckHWD MM4, MM0 + + PAddD MM2, [SI] + PSRAWI MM1, RAMPSPEED-1 + + PAddD MM4, [SI+8] + PAddW MM6, MM1 ; MM6 = new volume (ramped) + + MovQM [SI], MM2 + MovQ MM1, MM6 + + MovQ MM2, [DS:0] + PMulHW MM1, MM3 + + MovQM [SI+8], MM4 + PMulLW MM3, MM6 + + MovQ MM0, MM3 + PUnpckLWD MM3, MM1 + + PAddD MM3, [SI+10h] + PUnpckHWD MM0, MM1 + + MovQM [SI+10h], MM3 + PSubW MM2, MM6 + + PAddD MM0, [SI+18h] + PSRAWI MM2, RAMPSPEED-1 + + MovQM [SI+18h], MM0 + PAddW MM6, MM2 + +M32Bit8MVPannedEnd: +IF MONITORPERFORMANCE + RdTSC + Add CS:M32BitMICounter8BitTicksLow, EAX + AdC CS:M32BitMICounter8BitTicksHigh, EDX +ENDIF + Ret + +EndP M32Bit8MVPanned + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreM32BitMVPanned + Assume DS:Driver + + Mov ES, CS:MixSegment + + Mov AX, [SI+0Ch] ; AX = destination left + Mov BX, [SI+1Ch] ; BX = current left + Mov CX, [SI+0Eh] ; CX = destination right + Mov DX, [SI+1Eh] ; DX = current right. + + Cmp AX, BX + JL PreM32BitMVPannedV1 + + Add AX, RAMPCOMPENSATE + +PreM32BitMVPannedV1: + Cmp CX, DX + JL PreM32BitMVPannedV2 + + Add CX, RAMPCOMPENSATE + +PreM32BitMVPannedV2: + Sub Word Ptr [SI+8], 60 + + Mov [Word Ptr ES:0], AX + Mov [Word Ptr ES:4], AX + Mov [Word Ptr ES:2], CX + Mov [Word Ptr ES:6], CX + + Mov [CS:M32BitMIVolumeData], BX + Mov [CS:M32BitMIVolumeData+2], DX + + Sub AX, BX + Sub CX, DX + + SAR AX, RAMPSPEED + SAR CX, RAMPSPEED + + Add BX, AX + Add DX, CX + + Mov [CS:M32BitMIVolumeData+4], BX + Mov [CS:M32BitMIVolumeData+6], DX + + SegCS MovQ MM6, M32BitMIVolumeData + + Ret + +EndP PreM32BitMVPanned + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + diff --git a/SoundDrivers/M32ULTRA.INC b/SoundDrivers/M32ULTRA.INC new file mode 100755 index 0000000..50b693f --- /dev/null +++ b/SoundDrivers/M32ULTRA.INC @@ -0,0 +1,49 @@ + + DW Offset UpdateNoLoop, 0, 0, 0, 0 ; Update only + DW Offset UpdateForwardsLoop, 0, 0, 0, 0 + DW Offset UpdatePingPongLoop, 0, 0, 0, 0 + ; Left only + DW Offset MixNoLoop, PreMixUltraLeft8BitI, MFS8Bit, MBS8Bit, MixUltraSingle8BitI + DW Offset MixForwardsLoop, PreMixUltraLeft8BitI, MFS8Bit, MBS8Bit, MixUltraSingle8BitI + DW Offset MixPingPongLoop, PreMixUltraLeft8BitI, MFS8Bit, MBS8Bit, MixUltraSingle8BitI + ; Right only + DW Offset MixNoLoop, PreMixUltraRight8BitI, MFS8Bit, MBS8Bit, MixUltraSingle8BitI + DW Offset MixForwardsLoop, PreMixUltraRight8BitI, MFS8Bit, MBS8Bit, MixUltraSingle8BitI + DW Offset MixPingPongLoop, PreMixUltraRight8BitI, MFS8Bit, MBS8Bit, MixUltraSingle8BitI + ; Central + DW Offset MixNoLoop, PreMixUltraCentral8BitI, MFS8Bit, MBS8Bit, MixUltraCentral8BitI + DW Offset MixForwardsLoop, PreMixUltraCentral8BitI, MFS8Bit, MBS8Bit, MixUltraCentral8BitI + DW Offset MixPingPongLoop, PreMixUltraCentral8BitI, MFS8Bit, MBS8Bit, MixUltraCentral8BitI + ; Stereo + DW Offset MixNoLoop, PreMixUltraPanned8BitI, MFS8Bit, MBS8Bit, MixUltraPanned8BitI + DW Offset MixForwardsLoop, PreMixUltraPanned8BitI, MFS8Bit, MBS8Bit, MixUltraPanned8BitI + DW Offset MixPingPongLoop, PreMixUltraPanned8BitI, MFS8Bit, MBS8Bit, MixUltraPanned8BitI + ; Surround + DW Offset MixNoLoop, PreMixUltraSurround8BitI, MFS8Bit, MBS8Bit, MixUltraSurround8BitI + DW Offset MixForwardsLoop, PreMixUltraSurround8BitI, MFS8Bit, MBS8Bit, MixUltraSurround8BitI + DW Offset MixPingPongLoop, PreMixUltraSurround8BitI, MFS8Bit, MBS8Bit, MixUltraSurround8BitI + + ; 16 bit tables + DW Offset UpdateNoLoop, 0, 0, 0, 0 ; Update only + DW Offset UpdateForwardsLoop, 0, 0, 0, 0 + DW Offset UpdatePingPongLoop, 0, 0, 0, 0 + ; Left only + DW Offset MixNoLoop, PreMixUltraLeft16BitI, MFS16Bit, MBS16Bit, MixUltraSingle16BitI + DW Offset MixForwardsLoop, PreMixUltraLeft16BitI, MFS16Bit, MBS16Bit, MixUltraSingle16BitI + DW Offset MixPingPongLoop, PreMixUltraLeft16BitI, MFS16Bit, MBS16Bit, MixUltraSingle16BitI + ; Right only + DW Offset MixNoLoop, PreMixUltraRight16BitI, MFS16Bit, MBS16Bit, MixUltraSingle16BitI + DW Offset MixForwardsLoop, PreMixUltraRight16BitI, MFS16Bit, MBS16Bit, MixUltraSingle16BitI + DW Offset MixPingPongLoop, PreMixUltraRight16BitI, MFS16Bit, MBS16Bit, MixUltraSingle16BitI + ; Central + DW Offset MixNoLoop, PreMixUltraCentral16BitI, MFS16Bit, MBS16Bit, MixUltraCentral16BitI + DW Offset MixForwardsLoop, PreMixUltraCentral16BitI, MFS16Bit, MBS16Bit, MixUltraCentral16BitI + DW Offset MixPingPongLoop, PreMixUltraCentral16BitI, MFS16Bit, MBS16Bit, MixUltraCentral16BitI + ; Stereo + DW Offset MixNoLoop, PreMixUltraPanned16BitI, MFS16Bit, MBS16Bit, MixUltraPanned16BitI + DW Offset MixForwardsLoop, PreMixUltraPanned16BitI, MFS16Bit, MBS16Bit, MixUltraPanned16BitI + DW Offset MixPingPongLoop, PreMixUltraPanned16BitI, MFS16Bit, MBS16Bit, MixUltraPanned16BitI + ; Surround + DW Offset MixNoLoop, PreMixUltraSurround16BitI, MFS16Bit, MBS16Bit, MixUltraSurround16BitI + DW Offset MixForwardsLoop, PreMixUltraSurround16BitI, MFS16Bit, MBS16Bit, MixUltraSurround16BitI + DW Offset MixPingPongLoop, PreMixUltraSurround16BitI, MFS16Bit, MBS16Bit, MixUltraSurround16BitI diff --git a/SoundDrivers/M32ULTRA.MIX b/SoundDrivers/M32ULTRA.MIX new file mode 100755 index 0000000..f9d89ad --- /dev/null +++ b/SoundDrivers/M32ULTRA.MIX @@ -0,0 +1,770 @@ + + ; Different mixing routines required: + ; Left } shared + ; Right } + ; Central + ; Surround + ; Panned ; Each requires 8 bit and 16 bit + ; Single output - for Mono, pure left/pure right + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +GetUltra8BitWaveform Macro ; Puts waveform value in EBX, range -32k->+32k + + Push EDX + Push EBP + + MovSX EDX, Byte Ptr [ES:DI+2] ; v + MovSX EBX, Byte Ptr [ES:DI] ; t + MovSX EAX, Byte Ptr [ES:DI+1] ; u + + LEA EBP, [EBX+EDX] ; v+t + SAR EBP, 1 + Sub EBP, EAX ; (v+t)/2 - u + IMul EBP, ECX ; ax in 8.16 format + SAR EBP, 10 ; ax in 8.6 format + + ShL EAX, 7 ; EBX = 2u<<6 + Add EDX, EBX ; EDX = v+t + Add EBX, EBX ; EAX = 2t + Add EBP, EAX ; EBP = ax+2u + Add EDX, EBX ; 3t+v + ShL EDX, 5 ; (3t+v)/2 << 6 + Sub EBP, EDX ; ax+b + + ShL EBX, 7 + + IMul EBP, ECX ; ax^2+bx in 8.22 form + SAR EBP, 14 ; ax^2+bx in 8.8 form + + Add EBX, EBP ; ax^2+bx+c + + Pop EBP + Pop EDX + +EndM + +GetUltra16BitWaveform Macro ; Puts waveform value in EBX, range -32k->+32k + + Push ECX + Push EDX + Push EBP + + MovSX EDX, Word Ptr [ES:EDI+EDI+4] ; v + MovSX EBX, Word Ptr [ES:EDI+EDI] ; t + MovSX EAX, Word Ptr [ES:EDI+EDI+2] ; u + + ShR ECX, 3 ; 0.13 + LEA EBP, [EBX+EDX] + SAR EBP, 1 + Sub EBP, EAX ; (v+t)/2 - u + IMul EBP, ECX ; 16.13 + SAR EBP, 14 ; 15.0 + + Add EDX, EBX ; EDX = v+t + Add EBP, EAX ; EBP = ax+2u + LEA EDX, [EDX+EBX*2] + SAR EDX, 2 ; EDX = (3t+v)/2 + Sub EBP, EDX ; ax + b, 15 form + + IMul EBP, ECX ; ax^2+bx in 15.13 form + SAR EBP, 12 ; ax^2+bx in 16.0 form + + Add EBX, EBP + + Pop EBP + Pop EDX + Pop ECX + +EndM + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MUltraMix8ISingle Macro Index + +MUltraMix8ISingle&Index&: + GetUltra8BitWaveForm + +MUltraMix8ISingleVolume&Index& EQU $+3 + IMul EAX, EBX, 8000h + + Add ERROR, DELTAERROR ;; 1 + AdC DI, DELTAOFFSET ;; 1 + Sub [SI+(Index-3)*8], EAX ;; 3 +EndM + +MUltraMix8ICentral Macro Index + +MUltraMix8ICentral&Index&: + GetUltra8BitWaveForm + +MUltraMix8ICentralVolume&Index& EQU $+3 + IMul EAX, EBX, 8000h + + Add ERROR, DELTAERROR ;; 1 + AdC DI, DELTAOFFSET ;; 1 + Sub [SI+(Index-3)*8], EAX ;; 4 + Sub [SI+(Index-3)*8+4], EAX ;; 4 + +EndM + +MUltraMix8ISurround Macro Index + +MUltraMix8ISurround&Index&: + GetUltra8BitWaveForm + +MUltraMix8ISurroundVolume&Index& EQU $+3 + IMul EAX, EBX, 8000h + + Add ERROR, DELTAERROR ;; 1 + AdC DI, DELTAOFFSET ;; 1 + Sub [SI+(Index-3)*8], EAX ;; 4 + Add [SI+(Index-3)*8+4], EAX ;; 4 + +EndM + + ; Panned output +MUltraMix8IPanned Macro Index + +MUltraMix8IPanned&Index&: + Get32Bit8WaveForm + +MUltraMix8ILeftVolume&Index& EQU $+3 + IMul EAX, EBX, 8000h +MUltraMix8IRightVolume&Index& EQU $+3 + IMul EBX, EBX, 8000h + + Sub [SI+(Index-3)*8], EAX ;; 4 + Sub [SI+(Index-3)*8+4], EBX ;; 4 + + Add ERROR, DELTAERROR ;; 1 + AdC DI, DELTAOFFSET ;; 1 + +EndM + +MUltraMix16ISingle Macro Index + +MUltraMix16ISingle&Index&: + GetUltra16BitWaveForm + +MUltraMix16ISingleVolume&Index& EQU $+3 + IMul EAX, EBX, 8000h + + Add ERROR, DELTAERROR ;; 1 + AdC DI, DELTAOFFSET ;; 1 + Sub [SI+(Index-3)*8], EAX ;; 3 + +EndM + +MUltraMix16ICentral Macro Index + +MUltraMix16ICentral&Index&: + GetUltra16BitWaveForm + +MUltraMix16ICentralVolume&Index& EQU $+3 + IMul EAX, EBX, 8000h + + Add ERROR, DELTAERROR ;; 1 + AdC DI, DELTAOFFSET ;; 1 + Sub [SI+(Index-3)*8], EAX ;; 3 + Sub [SI+(Index-3)*8+4], EAX ;; 3 + +EndM + +MUltraMix16ISurround Macro Index + +MUltraMix16ISurround&Index&: + GetUltra16BitWaveForm + +MUltraMix16ISurroundVolume&Index& EQU $+3 + IMul EAX, EBX, 8000h + + Add ERROR, DELTAERROR ;; 1 + AdC DI, DELTAOFFSET ;; 1 + Sub [SI+(Index-3)*8], EAX ;; 3 + Add [SI+(Index-3)*8+4], EAX ;; 3 + +EndM + + ; Panned output +MUltraMix16IPanned Macro Index + +MUltraMix16IPanned&Index&: + GetUltra16BitWaveForm + +MUltraMix16ILeftVolume&Index& EQU $+3 + IMul EAX, EBX, 8000h +MUltraMix16IRightVolume&Index& EQU $+3 + IMul EBX, EBX, 8000h + + Sub [SI+(Index-3)*8], EAX + Sub [SI+(Index-3)*8+4], EBX + + Add ERROR, DELTAERROR + AdC DI, DELTAOFFSET + +EndM + +;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ + +MixUltraSingle8BitIOffsetTable Label Word + + IndexCounter = 3 + + MUltraMix8ISingleOffset Macro Index + DW Offset MUltraMix8ISingle&Index& + EndM + + REPT 4 + MUltraMix8ISingleOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc MixUltraSingle8BitI + ; AX = count... + + ; Number of times to loop = (Count-1) / 16 + + Dec AX + Mov BX, AX + And AX, 3 + ShR BX, 2 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Jmp [CS:MixUltraSingle8BitIOffsetTable+BX] + + MUltraMix8ISingle 0 + MUltraMix8ISingle 1 + MUltraMix8ISingle 2 + MUltraMix8ISingle 3 + + Add SI, 4*MIXRESOLUTION/4 + Dec LoopCounter + JNZ MUltraMix8ISingle0 + + Ret + +EndP MixUltraSingle8BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMixUltraLeft8BitI + + Mov AX, [SI+0Eh] + +PreMixUltraLeft8BitI1: + IndexCounter = 0 + + PreMixUltraSingleMacro Macro Index + Mov Word Ptr [CS:MUltraMix8ISingleVolume&Index&], AX + EndM + + REPT 4 + PreMixUltraSingleMacro %IndexCounter + IndexCounter = IndexCounter+1 + EndM + Ret + +EndP PreMixUltraLeft8BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMixUltraRight8BitI + + Add MixBufferOffset, MixResolution/8 + Mov AX, [SI+0Ch] + Jmp PreMixUltraLeft8BitI1 + +EndP PreMixUltraRight8BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixUltraCentral8BitIOffsetTable Label Word + + IndexCounter = 3 + + MUltraMix8ICentralOffset Macro Index + DW Offset MUltraMix8ICentral&Index& + EndM + + REPT 4 + MUltraMix8ICentralOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc MixUltraCentral8BitI + + Dec AX + Mov BX, AX + And AX, 3 + ShR BX, 2 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Jmp [CS:MixUltraCentral8BitIOffsetTable+BX] + + MUltraMix8ICentral 0 + MUltraMix8ICentral 1 + MUltraMix8ICentral 2 + MUltraMix8ICentral 3 + + Add SI, 4*MIXRESOLUTION/4 + Dec LoopCounter + JNZ MUltraMix8ICentral0 + + Ret + +EndP MixUltraCentral8BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMixUltraCentral8BitI + + Mov AX, [SI+0Eh] + + IndexCounter = 0 + + PreMixUltraCentralMacro Macro Index + Mov Word Ptr [CS:MUltraMix8ICentralVolume&Index&], AX + EndM + + REPT 4 + PreMixUltraCentralMacro %IndexCounter + IndexCounter = IndexCounter+1 + EndM + + Ret + +EndP PreMixUltraCentral8BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixUltraSurround8BitIOffsetTable Label Word + + IndexCounter = 3 + + MUltraMix8ISurroundOffset Macro Index + DW Offset MUltraMix8ISurround&Index& + EndM + + REPT 4 + MUltraMix8ISurroundOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc MixUltraSurround8BitI + + Dec AX + Mov BX, AX + And AX, 3 + ShR BX, 2 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Jmp [CS:MixUltraSurround8BitIOffsetTable+BX] + + MUltraMix8ISurround 0 + MUltraMix8ISurround 1 + MUltraMix8ISurround 2 + MUltraMix8ISurround 3 + + Add SI, 4*MIXRESOLUTION/4 + Dec LoopCounter + JNZ MUltraMix8ISurround0 + + Ret + +EndP MixUltraSurround8BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMixUltraSurround8BitI + + Mov AX, [SI+0Eh] + + IndexCounter = 0 + + PreMixUltraSurroundMacro Macro Index + Mov Word Ptr [CS:MUltraMix8ISurroundVolume&Index&], AX + EndM + + REPT 4 + PreMixUltraSurroundMacro %IndexCounter + IndexCounter = IndexCounter+1 + EndM + + Ret + +EndP PreMixUltraSurround8BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixUltraPanned8BitIOffsetTable Label Word + + IndexCounter = 3 + + MUltraMix8IPannedOffset Macro Index + DW Offset MUltraMix8IPanned&Index& + EndM + + REPT 4 + MUltraMix8IPannedOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc MixUltraPanned8BitI + + Dec AX + Mov BX, AX + And AX, 3 + ShR BX, 2 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Jmp [CS:MixUltraPanned8BitIOffsetTable+BX] + + MUltraMix8IPanned 0 + MUltraMix8IPanned 1 + MUltraMix8IPanned 2 + MUltraMix8IPanned 3 + + Add SI, 4*MIXRESOLUTION/4 + Dec LoopCounter + JNZ MUltraMix8IPanned0 + + Ret + +EndP MixUltraPanned8BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMixUltraPanned8BitI + + Mov AX, [SI+0Eh] ; Left + Mov BX, [SI+0Ch] ; Right + + IndexCounter = 0 + + PreMixUltraPannedMacro Macro Index + Mov Word Ptr [CS:MUltraMix8ILeftVolume&Index&], AX + Mov Word Ptr [CS:MUltraMix8IRightVolume&Index&], BX + EndM + + REPT 4 + PreMixUltraPannedMacro %IndexCounter + IndexCounter = IndexCounter+1 + EndM + + Ret + +EndP PreMixUltraPanned8BitI + +;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ + +MixUltraSingle16BitIOffsetTable Label Word + + IndexCounter = 3 + + MUltraMix16ISingleOffset Macro Index + DW Offset MUltraMix16ISingle&Index& + EndM + + REPT 4 + MUltraMix16ISingleOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc MixUltraSingle16BitI + ; AX = count... + + ; Number of times to loop = (Count-1) / 16 + + Dec AX + Mov BX, AX + And AX, 3 + ShR BX, 2 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Jmp [CS:MixUltraSingle16BitIOffsetTable+BX] + + MUltraMix16ISingle 0 + MUltraMix16ISingle 1 + MUltraMix16ISingle 2 + MUltraMix16ISingle 3 + + Add SI, 4*MIXRESOLUTION/4 + Dec LoopCounter + JNZ MUltraMix16ISingle0 + + Ret + +EndP MixUltraSingle16BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMixUltraLeft16BitI + + Mov AX, [SI+0Eh] ; Left + +PreMixUltraLeft16BitI1: + IndexCounter = 0 + + PreMixUltraSingleMacro Macro Index + Mov Word Ptr [CS:MUltraMix16ISingleVolume&Index&], AX + EndM + + REPT 4 + PreMixUltraSingleMacro %IndexCounter + IndexCounter = IndexCounter+1 + EndM + + Ret + +EndP PreMixUltraLeft16BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMixUltraRight16BitI + + Add MixBufferOffset, MixResolution/8 + Mov AX, [SI+0Ch] + Jmp PreMixUltraLeft16BitI1 + + Ret + +EndP PreMixUltraRight16BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixUltraCentral16BitIOffsetTable Label Word + + IndexCounter = 3 + + MUltraMix16ICentralOffset Macro Index + DW Offset MUltraMix16ICentral&Index& + EndM + + REPT 4 + MUltraMix16ICentralOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc MixUltraCentral16BitI + + Dec AX + Mov BX, AX + And AX, 3 + ShR BX, 2 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Jmp [CS:MixUltraCentral16BitIOffsetTable+BX] + + MUltraMix16ICentral 0 + MUltraMix16ICentral 1 + MUltraMix16ICentral 2 + MUltraMix16ICentral 3 + + Add SI, 4*MIXRESOLUTION/4 + Dec LoopCounter + JNZ MUltraMix16ICentral0 + + Ret + +EndP MixUltraCentral16BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMixUltraCentral16BitI + + Mov AX, [SI+0Eh] + + IndexCounter = 0 + + PreMixUltraCentralMacro Macro Index + Mov Word Ptr [CS:MUltraMix16ICentralVolume&Index&], AX + EndM + + REPT 4 + PreMixUltraCentralMacro %IndexCounter + IndexCounter = IndexCounter+1 + EndM + + Ret + +EndP PreMixUltraCentral16BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixUltraSurround16BitIOffsetTable Label Word + + IndexCounter = 3 + + MUltraMix16ISurroundOffset Macro Index + DW Offset MUltraMix16ISurround&Index& + EndM + + REPT 4 + MUltraMix16ISurroundOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc MixUltraSurround16BitI + + Dec AX + Mov BX, AX + And AX, 3 + ShR BX, 2 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Jmp [CS:MixUltraSurround16BitIOffsetTable+BX] + + MUltraMix16ISurround 0 + MUltraMix16ISurround 1 + MUltraMix16ISurround 2 + MUltraMix16ISurround 3 + + Add SI, 4*MIXRESOLUTION/4 + Dec LoopCounter + JNZ MUltraMix16ISurround0 + + Ret + +EndP MixUltraSurround16BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMixUltraSurround16BitI + + Mov AX, [SI+0Eh] + + IndexCounter = 0 + + PreMixUltraSurroundMacro Macro Index + Mov Word Ptr [CS:MUltraMix16ISurroundVolume&Index&], AX + EndM + + REPT 4 + PreMixUltraSurroundMacro %IndexCounter + IndexCounter = IndexCounter+1 + EndM + + Ret + +EndP PreMixUltraSurround16BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixUltraPanned16BitIOffsetTable Label Word + + IndexCounter = 3 + + MUltraMix16IPannedOffset Macro Index + DW Offset MUltraMix16IPanned&Index& + EndM + + REPT 4 + MUltraMix16IPannedOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc MixUltraPanned16BitI + + Dec AX + Mov BX, AX + And AX, 3 + ShR BX, 2 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Jmp [CS:MixUltraPanned16BitIOffsetTable+BX] + +PanMUltraBit16ILoop: + MUltraMix16IPanned 0 + MUltraMix16IPanned 1 + MUltraMix16IPanned 2 + MUltraMix16IPanned 3 + + Add SI, 4*MIXRESOLUTION/4 + Dec LoopCounter + JNZ PanMUltraBit16ILoop + + Ret + +EndP MixUltraPanned16BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMixUltraPanned16BitI + + Mov AX, [SI+0Eh] ; Left + Mov BX, [SI+0Ch] ; Right + + IndexCounter = 0 + + PreMixUltraPannedMacro Macro Index + Mov Word Ptr [CS:MUltraMix16ILeftVolume&Index&], AX + Mov Word Ptr [CS:MUltraMix16IRightVolume&Index&], BX + EndM + + REPT 4 + PreMixUltraPannedMacro %IndexCounter + IndexCounter = IndexCounter+1 + EndM + + Ret + +EndP PreMixUltraPanned16BitI + + diff --git a/SoundDrivers/MAD.BAT b/SoundDrivers/MAD.BAT new file mode 100755 index 0000000..ec622a2 --- /dev/null +++ b/SoundDrivers/MAD.BAT @@ -0,0 +1,5 @@ +tasm /m /ut310 ad1816 +tlink /3 ad1816 +execom ad1816 itad1816.drv +copy itad1816.drv .. + diff --git a/SoundDrivers/MAWE.BAT b/SoundDrivers/MAWE.BAT new file mode 100755 index 0000000..57cafac --- /dev/null +++ b/SoundDrivers/MAWE.BAT @@ -0,0 +1,4 @@ +tasm /m /ut310 awe32drv +tlink /3 awe32drv +execom awe32drv itawe32.drv +copy itawe32.drv .. diff --git a/SoundDrivers/MAWEB.BAT b/SoundDrivers/MAWEB.BAT new file mode 100755 index 0000000..20145cd --- /dev/null +++ b/SoundDrivers/MAWEB.BAT @@ -0,0 +1,4 @@ +tasm /m /ut310 awe32b +tlink /3 awe32b +execom awe32b itawe32b.drv +copy itawe32b.drv .. diff --git a/SoundDrivers/MB.BAT b/SoundDrivers/MB.BAT new file mode 100755 index 0000000..de7ae06 --- /dev/null +++ b/SoundDrivers/MB.BAT @@ -0,0 +1,6 @@ +@rem Base1 Driver +tasm /m /ut310 base1 +tlink /3 base1 +execom base1 itbase1.drv +copy itbase1.drv .. + diff --git a/SoundDrivers/MES.BAT b/SoundDrivers/MES.BAT new file mode 100755 index 0000000..c3e86fa --- /dev/null +++ b/SoundDrivers/MES.BAT @@ -0,0 +1,5 @@ +tasm /m /ut310 es1868 +tlink /3 es1868 +execom es1868 ites1868.drv +copy ites1868.drv .. + diff --git a/SoundDrivers/MES1688.BAT b/SoundDrivers/MES1688.BAT new file mode 100755 index 0000000..890cbb1 --- /dev/null +++ b/SoundDrivers/MES1688.BAT @@ -0,0 +1,5 @@ +tasm /m /ut310 es1688 +tlink /3 es1688 +execom es1688 ites1688.drv +copy ites1688.drv .. + diff --git a/SoundDrivers/MES1688M.BAT b/SoundDrivers/MES1688M.BAT new file mode 100755 index 0000000..0f25644 --- /dev/null +++ b/SoundDrivers/MES1688M.BAT @@ -0,0 +1,5 @@ +tasm32 /m /ut310 es1688mx +tlink /3 es1688mx +execom es1688mx ites1688.mmx +copy ites1688.mmx .. + diff --git a/SoundDrivers/MES1788.BAT b/SoundDrivers/MES1788.BAT new file mode 100755 index 0000000..01230e5 --- /dev/null +++ b/SoundDrivers/MES1788.BAT @@ -0,0 +1,5 @@ +tasm /m /ut310 es1788 +tlink /3 es1788 +execom es1788 ites1788.drv +copy ites1788.drv .. + diff --git a/SoundDrivers/MES1869.BAT b/SoundDrivers/MES1869.BAT new file mode 100755 index 0000000..4e98784 --- /dev/null +++ b/SoundDrivers/MES1869.BAT @@ -0,0 +1,5 @@ +tasm /m /ut310 es1869 +tlink /3 es1869 +execom es1869 ites1869.drv +copy ites1869.drv .. + diff --git a/SoundDrivers/MES1869M.BAT b/SoundDrivers/MES1869M.BAT new file mode 100755 index 0000000..ac92bef --- /dev/null +++ b/SoundDrivers/MES1869M.BAT @@ -0,0 +1,5 @@ +tasm32 /m /ut310 es1869mx +tlink /3 es1869mx +execom es1869mx ites1869.mmx +copy ites1869.mmx .. + diff --git a/SoundDrivers/MESM.BAT b/SoundDrivers/MESM.BAT new file mode 100755 index 0000000..9c3ba08 --- /dev/null +++ b/SoundDrivers/MESM.BAT @@ -0,0 +1,5 @@ +tasm32 /m /ut310 es1868mx +tlink /3 es1868mx +execom es1868mx ites1868.mmx +copy ites1868.mmx .. + diff --git a/SoundDrivers/MEWS.BAT b/SoundDrivers/MEWS.BAT new file mode 100755 index 0000000..a69f9b3 --- /dev/null +++ b/SoundDrivers/MEWS.BAT @@ -0,0 +1,4 @@ +tasm /m /ut310 ews64 +tlink /3 ews64 +execom ews64 itews64.drv +copy itews64.drv .. diff --git a/SoundDrivers/MEWSC.BAT b/SoundDrivers/MEWSC.BAT new file mode 100755 index 0000000..582f17e --- /dev/null +++ b/SoundDrivers/MEWSC.BAT @@ -0,0 +1,5 @@ +tasm /m /ut310 ewscodec +tlink /3 ewscodec +execom ewscodec itewscod.drv +copy itewscod.drv .. + diff --git a/SoundDrivers/MEWSCM.BAT b/SoundDrivers/MEWSCM.BAT new file mode 100755 index 0000000..d74f03f --- /dev/null +++ b/SoundDrivers/MEWSCM.BAT @@ -0,0 +1,5 @@ +tasm32 /m /ut310 ewscodmx +tlink /3 ewscodmx +execom ewscodmx itewscod.mmx +copy itewscod.mmx .. + diff --git a/SoundDrivers/MG16.BAT b/SoundDrivers/MG16.BAT new file mode 100755 index 0000000..b0db2a1 --- /dev/null +++ b/SoundDrivers/MG16.BAT @@ -0,0 +1,5 @@ +tasm /m /ut310 gold16 +tlink /3 gold16 +execom m16 itgold16.drv +copy itgold16.drv .. + diff --git a/SoundDrivers/MGP.BAT b/SoundDrivers/MGP.BAT new file mode 100755 index 0000000..b7626ff --- /dev/null +++ b/SoundDrivers/MGP.BAT @@ -0,0 +1,4 @@ +tasm /m /ut310 guspnpm +tlink /3 guspnpm +execom guspnpm itguspnp.drv +copy itguspnp.drv .. diff --git a/SoundDrivers/MGPM.BAT b/SoundDrivers/MGPM.BAT new file mode 100755 index 0000000..c5a95e6 --- /dev/null +++ b/SoundDrivers/MGPM.BAT @@ -0,0 +1,4 @@ +tasm32 /m /ut310 guspnpmx +tlink /3 guspnpmx +execom guspnpmx itguspnp.mmx +copy itguspnp.mmx .. diff --git a/SoundDrivers/MGUS.BAT b/SoundDrivers/MGUS.BAT new file mode 100755 index 0000000..30120d1 --- /dev/null +++ b/SoundDrivers/MGUS.BAT @@ -0,0 +1,4 @@ +tasm /m /uT310 /l gushiqdr +tlink /3 gushiqdr +execom gushiqdr itgus.drv +copy itgus.drv .. diff --git a/SoundDrivers/MGUS2.BAT b/SoundDrivers/MGUS2.BAT new file mode 100755 index 0000000..328066a --- /dev/null +++ b/SoundDrivers/MGUS2.BAT @@ -0,0 +1,4 @@ +tasm /m /uT310 gushiq2 +tlink /3 gushiq2 +execom gushiq2 itgus2.drv +copy itgus2.drv .. diff --git a/SoundDrivers/MGUSLO.BAT b/SoundDrivers/MGUSLO.BAT new file mode 100755 index 0000000..7141a75 --- /dev/null +++ b/SoundDrivers/MGUSLO.BAT @@ -0,0 +1,4 @@ +tasm /m /uT310 gusdrv2 +tlink /3 gusdrv2 +execom gusdrv2 itguslo.drv +copy itguslo.drv .. diff --git a/SoundDrivers/MGUSMAX.BAT b/SoundDrivers/MGUSMAX.BAT new file mode 100755 index 0000000..46b43d4 --- /dev/null +++ b/SoundDrivers/MGUSMAX.BAT @@ -0,0 +1,5 @@ +tasm /m /ut310 gusmax +tlink /3 gusmax +execom gusmax itgusmax.drv +copy itgusmax.drv .. + diff --git a/SoundDrivers/MGUSMAXM.BAT b/SoundDrivers/MGUSMAXM.BAT new file mode 100755 index 0000000..b88175b --- /dev/null +++ b/SoundDrivers/MGUSMAXM.BAT @@ -0,0 +1,5 @@ +tasm32 /m /ut310 gusmaxmx +tlink /3 gusmaxmx +execom gusmaxmx itgusmax.mmx +copy itgusmax.mmx .. + diff --git a/SoundDrivers/MGUSMIX.BAT b/SoundDrivers/MGUSMIX.BAT new file mode 100755 index 0000000..3b27517 --- /dev/null +++ b/SoundDrivers/MGUSMIX.BAT @@ -0,0 +1,4 @@ +tasm /m /ut310 gusmixdr +tlink /3 gusmixdr +execom gusmixdr itgusmix.drv +copy itgusmix.drv .. diff --git a/SoundDrivers/MIDDRV.ASM b/SoundDrivers/MIDDRV.ASM new file mode 100755 index 0000000..d9adff2 --- /dev/null +++ b/SoundDrivers/MIDDRV.ASM @@ -0,0 +1,865 @@ + +; +; MID File generator +; + +REPEATSTATUSBYTE EQU 0 + + .486P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include ..\wavswitc.inc + +FileHandle DW 0 + +MIDOutputMsg DB "MIDI File Generator", 13 + DB "Writing to disk", 0 +MIDOutputError DB "Unable to create output file!", 0FFh, 29, " ", 0 +WriteErrorMsg DB "Error writing to output file. Output file closed", 0FFh, 11, " ", 0 +ClosedMsg DB "Closed output file", 0FFh, 42, " ", 0 +CreateMsg DB "Creating file " +Filename DB " ", 0 +OUTPUT DB "OUTPUT" +DriverName DB "ITMID.DRV", 0 + +CONFIGURATIONOFFSET EQU $+128 +CONFIGSIZE EQU 80 +MIDDirectory DB ".", 79 Dup (0) + + +AccumulatedTime DD 0 + +MIDIHEADERSIZE = 22+32+7 +MIDIHeader DB "MThd", 0, 0, 0, 6, 0, 0, 0, 1 + DB 0, 018h ; 24 ppqn + DB "MTrk" +MIDIFileSize DD 0 + DB 0, 0FFh, 01, 28 + DB "Created with Impulse Tracker" + DB 0, 0FFh, 51h, 3 +InitialTempo DD 0 + +MTrkEnd DB 0, 0FFh, 2Fh, 0 + +MIDIBuffer DB 256 Dup (0) +MIDIBufferOffset DW Offset MIDIBuffer + +MIDScreenList DW 6 + DW IdleFunctionList + DW GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr MIDHeader + + DW Near Ptr DirectoryInputText + DW Near Ptr DirectoryInputBox + DW Near Ptr DirectoryInput ; 6 + + DW 0 + +IdleFunctionList DD 0 + DD 0 +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +MIDHeader DW 10 + DB "MIDI File Export Driver", 0 + +DirectoryInputText DW 1 + DB 2, 14 + DB 20h + DB "Output Directory", 0 + +DirectoryInputBox DW 0 + DB 18, 13, 78, 15 + DB 25 + +DirectoryInput DW 16 + DB 19, 14 +Segment1 DW 0 + DW Offset MIDDirectory + DW 59 + DD 0 + DW 0FFFFh, 0FFFFh, 0FFFFh, 0FFFFh + +TRACEENABLED EQU 0 +CREATENEWLOGFILE EQU 1 +include debug.inc + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far + + Mov EAX, 'Jeff' + + ClC + Ret + +EndP DetectCard + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + + Mov Segment1, DS + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + Call GotoHomeDirectory + Mov SI, Offset MIDDirectory + Call SetDirectory + + Mov SI, Offset MIDOutputMsg + ClC + Ret + +EndP InitSound + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + Ret + +EndP ReInitSound + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc CheckFileClosed + + Push CS + Pop DS + Assume DS:Driver + + Mov BX, FileHandle + Test BX, BX + JZ CheckFileClosedEnd + + Mov AH, 40h + Mov CX, 4 + Mov DX, Offset MTrkEnd + Int 21h + + Mov FileHandle, 0 + + Mov AX, 4200h ; Move to start of file + Xor CX, CX + Xor DX, DX + Int 21h ; Start of file + + Mov AX, Word Ptr [MIDIFileSize] + Mov DX, Word Ptr [MIDIFileSize+2] + XChg AL, DH + XChg AH, DL + Mov Word Ptr [MIDIFileSize], AX + Mov Word Ptr [MIDIFileSize+2], DX + + Mov AH, 40h + Mov CX, MIDIHEADERSIZE + Mov DX, Offset MIDIHeader + Int 21h + + Mov AH, 3Eh + Int 21h + + Mov SI, Offset ClosedMsg + Mov BX, 40 + Call SetInfoLine + +CheckFileClosedEnd: + Ret + +EndP CheckFileClosed + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Call GotoHomeDirectory + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, 3D02h ; Read write access + Mov DX, Offset DriverName + Int 21h + JC SaveConfig2 + + Mov BX, AX + + Mov AX, 4200h + Xor CX, CX + Mov DX, Offset CONFIGURATIONOFFSET + Int 21h + JC SaveConfig1 + + Mov AH, 40h + Mov CX, CONFIGSIZE + Mov DX, Offset MIDDirectory + Int 21h + +SaveConfig1: + Mov AH, 3Eh + Int 21h + +SaveConfig2: + Call CheckFileClosed + Ret + +EndP UnInitSound + Assume DS:Nothing + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WriteMIDIBlock + Assume DS:Driver + + Xor ECX, ECX + + Mov CX, MIDIBufferOffset + Mov DX, Offset MIDIBuffer + Mov AH, 40h + Mov BX, FileHandle + Sub CX, DX + JZ NoDataToWrite + + Add MIDIFileSize, ECX + + Trace "Writing MIDI block" + + Int 21h + +NoDataToWrite: + Mov MIDIBufferOffset, Offset MIDIBuffer + + Ret + +EndP WriteMIDIBlock + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + Assume DS:Nothing + + Mov CS:Countdown, 0 + Mov CS:MIDIBufferOffset, Offset MIDIBuffer + + Call Update ; Got DS:SI, CX + +; Scan through channels and if any channels are samples, turn them off. + +TurnOffSamples1: + Test Byte Ptr [SI], 1 ; Channel on? + JZ TurnOffSamples2 + + Mov Word Ptr [SI], 0 + + Test Byte Ptr [SI+3Ah], 80h + JNZ TurnOffSamples2 + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Signify channel off + +TurnOffSamples2: + Add SI, 128 + Loop TurnOffSamples1 + +; OK.. check whether any MIDI data requires dumping... also whether file +; needs to be created. + + Test AX, AX ; Currently not playing + JNZ Poll1 + + Call CheckFileClosed + Ret + +Poll1: + Push CS + Pop DS + Assume DS:Driver + + Cmp FileHandle, 0 + JNE Poll2 + + Trace "New file to create" + + Mov SI, Offset MIDDirectory + Call SetDirectory + + Xor EAX, EAX + Mov AccumulatedTime, EAX + Mov AL, 4+32+7 + Mov MIDIFileSize, EAX + +; Have to create a file + Call GetFileName + Assume DS:Nothing ; Returns DS:SI + Push CS + Pop ES + Mov DI, Offset FileName + + Push DI + + Mov CX, 12 + Mov AL, ' ' + Rep StosB + + Pop DI + + Cmp Byte Ptr [DS:SI], 0 + JE PollFileNameNone + Cmp Byte Ptr [DS:SI], '.' + JE PollFileNameNone + + Mov CX, 8 +PollFileName1: + LodsB + Cmp AL, 0 + JE PollFileNameExt + Cmp AL, '.' + JE PollFileNameExt + StosB + Loop PollFileName1 + Jmp PollFileNameExt + +PollFileNameNone: + Push CS + Pop DS + Mov SI, Offset Output + Mov CX, 6 + Rep MovsB + +PollFileNameExt: + Mov EAX, 'DIM.' + StosD + Xor AL, AL + StosB + + Push CS + Pop DS + Assume DS:Driver + + Mov SI, Offset CreateMsg + Mov BX, 40 + Call SetInfoLine + + Mov AH, 3Ch + Xor CX, CX + Mov DX, Offset Filename + Int 21h + JC WriteError + + Mov BX, AX + Mov FileHandle, BX + Trace "File opened" + +; Write header once + Push BX + Call GetTempo + Mov EAX, 60000000 + And EBX, 0FFFFh + Xor EDX, EDX + Div EBX ; EAX = microseconds per quarter note + + ShL EAX, 8 + BSwap EAX + Mov InitialTempo, EAX + Pop BX + + Mov AH, 40h + Mov CX, MIDIHEADERSIZE + Mov DX, Offset MIDIHeader + Int 21h + JC WriteError + + Trace "Header written" + +Poll2: + Call WriteMIDIBlock + JC WriteError + +; Update time counters + Inc AccumulatedTime + + Ret + +WriteError: + Call CheckFileClosed + Mov SI, Offset WriteErrorMsg + Mov BX, 40 + Call SetInfoLine + Call StopPlayback + + Ret + +EndP Poll + Assume DS:Nothing + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far ; Frames per second = 0.4*BX + ; -> Milliseconds per frame = 1000/(0.4/BX) + ; = 2500/BX + PushAD + Push DS + +; SetTempo: FF 51 03 tt tt tt + + Push CS + Pop DS + Assume DS:Driver + + Push BX + + Mov SI, MIDIBufferOffset + Call WriteDeltaTime + + Pop BX + + Mov DWord Ptr [SI], 351FFh + Add SI, 3 + + Mov EAX, 60000000 + And EBX, 0FFFFh + Xor EDX, EDX + Div EBX ; EAX = microseconds per quarter note + + ShL EAX, 8 + BSwap EAX + Mov DWord Ptr [SI], EAX + Add SI, 3 + + Mov MIDIBufferOffset, SI + + Pop DS + PopAD + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + Ret + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load (0 based) +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc LoadSample Far + + StC + Ret + +EndP LoadSample + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release (1 based) +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset MIDScreenList + + ClC + Ret + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far + + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far + + Ret + +EndP SetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +StatusByte DB 0 +CountDown DB 0 + +StatusByteLUT DB 2, 2, 2, 2, 1, 1, 2 +InSysex DW 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WriteDeltaTime ; Given DS:SI = buffer + + Xor EDX, EDX + Mov EBX, AccumulatedTime + Mov CX, 4 + Mov AccumulatedTime, EDX + +WriteDeltaTime1: + ShL EDX, 8 + Mov DL, BL + Or DL, 80h + ShR EBX, 7 + LoopNZ WriteDeltaTime1 + ; EDX = output bytes, DL = most signif + +WriteDeltaTime2: + Mov [SI], DL + Inc SI + ShR EDX, 8 + JNZ WriteDeltaTime2 + + And Byte Ptr [SI-1], 7Fh + + Ret + +EndP WriteDeltaTime + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc BufferMIDIOutput ; AL = value. + + PushAD + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov BX, InSysex + Mov SI, MIDIBufferOffset + + Test BX, BX + JZ BufferMIDINoSysex + + Cmp AL, 0F7h + JNE BufferMIDIOutput1 + + Mov DX, SI + Sub DX, BX ; DX = count of sysex bytes + Mov [BX], DL + Mov InSysex, 0 + + Jmp BufferMIDIOutput1 + +BufferMIDINoSysex: + Cmp Countdown, 0 + JNE BufferMIDIOutput1 + + Cmp AL, 0F0h + JA BufferMIDIOutput2 + +; Delta time required + Call WriteDeltaTime + + Xor BX, BX + Xor DL, DL + Test AL, AL + JNS BufferMIDINoStatus + Cmp AL, 0F0h + JE BufferMIDISysex + + Mov StatusByte, AL + Inc DX + Jmp BufferMIDINoStatus + +BufferMIDISysex: + Mov [SI], AL + Inc SI + Mov InSysex, SI + Jmp BufferMIDIOutput1 + +BufferMIDINoStatus: + Mov BL, StatusByte + ShR BX, 4 + Sub BL, 8 + JC BufferMIDIOutput1 + + Add DL, [StatusByteLUT+BX] + Mov Countdown, DL + +BufferMIDIOutput1: + Mov [SI], AL + Inc SI + Dec Countdown + + Mov MIDIBufferOffset, SI + + Cmp SI, Offset MIDIBuffer+200 + JB BufferMIDIOutput2 + Cmp InSysex, 0 + JNE BufferMIDIOutput2 + + Call WriteMIDIBlock + +BufferMIDIOutput2: + Pop DS + PopAD + + Ret + +EndP BufferMIDIOutput + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +InterpretState DB 0 +InterpretType DB 0 + +Proc SendUARTOut Far ; Local interpreter activated with 0F0h 0F0h. + + Mov AH, CS:InterpretState + Cmp AH, 2 + JB SendUARTOut1 + +; In interpreter. + JE SendUARTOut3 + +SendUARTOut4: + Mov CS:InterpretState, 0 + Ret + +SendUARTOut3: + Cmp AL, 2 + JAE SendUARTOut4 + + Mov CS:InterpretType, AL + Jmp SendUARTOutStateInc + +SendUARTOut1: + Cmp AL, 0F0h + JNE SendUARTOut2 + +SendUARTOutStateInc: + Inc CS:InterpretState + Ret + +SendUARTOut2: + Test AH, AH + JZ SendUARTOutEnd + + Push AX + Mov AL, 0F0h + Call BufferMIDIOutput + Pop AX + Mov CS:InterpretState, 0 + +SendUARTOutEnd: + Call BufferMIDIOutput + + Ret + +EndP SendUARTOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 32 ; Maximum number of channels the + ; driver can handle. +StopAfterPlay DW 1 +DefaultChannels DW 32 +DriverFlags DW 1 ; Supports MIDI Out. + + DW 4 Dup (0) + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + DW Offset SendUARTOut + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/MIDDRV2.ASM b/SoundDrivers/MIDDRV2.ASM new file mode 100755 index 0000000..74a2561 --- /dev/null +++ b/SoundDrivers/MIDDRV2.ASM @@ -0,0 +1,828 @@ + +; +; MID File generator +; + +REPEATSTATUSBYTE EQU 0 + + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include wavswitc.inc + +FileHandle DW 0 + +MIDOutputMsg DB "MIDI File Generator", 13 + DB "Writing to disk", 0 +MIDOutputError DB "Unable to create output file!", 0FFh, 29, " ", 0 +WriteErrorMsg DB "Error writing to output file. Output file closed", 0FFh, 11, " ", 0 +ClosedMsg DB "Closed output file", 0FFh, 42, " ", 0 +CreateMsg DB "Creating file " +Filename DB " ", 0 +OUTPUT DB "OUTPUT" +DriverName DB "ITMID.DRV", 0 + +CONFIGURATIONOFFSET EQU $+128 +CONFIGSIZE EQU 80 +MIDDirectory DB ".", 79 Dup (0) + + +AccumulatedTime DD 0 +AccumulatedTimeError DD 0 + +FrameTime DD 0 +FrameTimeError DD 0 + + +MIDIHeader DB "MThd", 0, 0, 0, 6, 0, 0, 0, 1, 0E7h, 28h + DB "MTrk" +MIDIFileSize DD 0 + DB 0, 0FFh, 01, 28 + DB "Created with Impulse Tracker" + +MTrkEnd DB 0, 0FFh, 2Fh, 0 + +MIDIBuffer DB 256 Dup (0) +MIDIBufferOffset DW Offset MIDIBuffer + +MIDScreenList DW 6 + DW IdleFunctionList + DW GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr MIDHeader + + DW Near Ptr DirectoryInputText + DW Near Ptr DirectoryInputBox + DW Near Ptr DirectoryInput ; 6 + + DW 0 + +IdleFunctionList DD 0 + DD 0 +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +MIDHeader DW 10 + DB "MIDI File Export Driver", 0 + +DirectoryInputText DW 1 + DB 2, 14 + DB 20h + DB "Output Directory", 0 + +DirectoryInputBox DW 0 + DB 18, 13, 78, 15 + DB 25 + +DirectoryInput DW 16 + DB 19, 14 +Segment1 DW 0 + DW Offset MIDDirectory + DW 59 + DD 0 + DW 0FFFFh, 0FFFFh, 0FFFFh, 0FFFFh + +TRACEENABLED EQU 0 +CREATENEWLOGFILE EQU 1 +include debug.inc + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far + + Mov EAX, 'Jeff' + + ClC + Ret + +EndP DetectCard + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + + Mov Segment1, DS + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + Call GotoHomeDirectory + Mov SI, Offset MIDDirectory + Call SetDirectory + + Mov SI, Offset MIDOutputMsg + ClC + Ret + +EndP InitSound + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + Ret + +EndP ReInitSound + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc CheckFileClosed + + Push CS + Pop DS + Assume DS:Driver + + Mov BX, FileHandle + Test BX, BX + JZ CheckFileClosedEnd + + Mov AH, 40h + Mov CX, 4 + Mov DX, Offset MTrkEnd + Int 21h + + Mov FileHandle, 0 + + Mov AX, 4200h ; Move to start of file + Xor CX, CX + Xor DX, DX + Int 21h ; Start of file + + Mov AX, Word Ptr [MIDIFileSize] + Mov DX, Word Ptr [MIDIFileSize+2] + XChg AL, DH + XChg AH, DL + Mov Word Ptr [MIDIFileSize], AX + Mov Word Ptr [MIDIFileSize+2], DX + + Mov AH, 40h + Mov CX, 22+32 + Mov DX, Offset MIDIHeader + Int 21h + + Mov AH, 3Eh + Int 21h + + Mov SI, Offset ClosedMsg + Mov BX, 40 + Call SetInfoLine + +CheckFileClosedEnd: + Ret + +EndP CheckFileClosed + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Call GotoHomeDirectory + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, 3D02h ; Read write access + Mov DX, Offset DriverName + Int 21h + JC SaveConfig2 + + Mov BX, AX + + Mov AX, 4200h + Xor CX, CX + Mov DX, Offset CONFIGURATIONOFFSET + Int 21h + JC SaveConfig1 + + Mov AH, 40h + Mov CX, CONFIGSIZE + Mov DX, Offset MIDDirectory + Int 21h + +SaveConfig1: + Mov AH, 3Eh + Int 21h + +SaveConfig2: + Call CheckFileClosed + Ret + +EndP UnInitSound + Assume DS:Nothing + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WriteMIDIBlock + Assume DS:Driver + + Xor ECX, ECX + + Mov CX, MIDIBufferOffset + Mov DX, Offset MIDIBuffer + Mov AH, 40h + Mov BX, FileHandle + Sub CX, DX + JZ NoDataToWrite + + Add MIDIFileSize, ECX + + Trace "Writing MIDI block" + + Int 21h + +NoDataToWrite: + Mov MIDIBufferOffset, Offset MIDIBuffer + + Ret + +EndP WriteMIDIBlock + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + Assume DS:Nothing + + Mov CS:Countdown, 0 + Mov CS:MIDIBufferOffset, Offset MIDIBuffer + + Call Update ; Got DS:SI, CX + +; Scan through channels and if any channels are samples, turn them off. + +TurnOffSamples1: + Test Byte Ptr [SI], 1 ; Channel on? + JZ TurnOffSamples2 + + Mov Word Ptr [SI], 0 + + Test Byte Ptr [SI+3Ah], 80h + JNZ TurnOffSamples2 + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Signify channel off + +TurnOffSamples2: + Add SI, 128 + Loop TurnOffSamples1 + +; OK.. check whether any MIDI data requires dumping... also whether file +; needs to be created. + + Test AX, AX ; Currently not playing + JNZ Poll1 + + Call CheckFileClosed + Ret + +Poll1: + Push CS + Pop DS + Assume DS:Driver + + Cmp FileHandle, 0 + JNE Poll2 + + Trace "New file to create" + + Mov SI, Offset MIDDirectory + Call SetDirectory + + Xor EAX, EAX + Mov AccumulatedTime, EAX + Mov AccumulatedTimeError, EAX + Mov AL, 4+32 + Mov MIDIFileSize, EAX + +; Have to create a file + Call GetFileName + Assume DS:Nothing ; Returns DS:SI + Push CS + Pop ES + Mov DI, Offset FileName + + Push DI + + Mov CX, 12 + Mov AL, ' ' + Rep StosB + + Pop DI + + Cmp Byte Ptr [DS:SI], 0 + JE PollFileNameNone + Cmp Byte Ptr [DS:SI], '.' + JE PollFileNameNone + + Mov CX, 8 +PollFileName1: + LodsB + Cmp AL, 0 + JE PollFileNameExt + Cmp AL, '.' + JE PollFileNameExt + StosB + Loop PollFileName1 + Jmp PollFileNameExt + +PollFileNameNone: + Push CS + Pop DS + Mov SI, Offset Output + Mov CX, 6 + Rep MovsB + +PollFileNameExt: + Mov EAX, 'DIM.' + StosD + Xor AL, AL + StosB + + Push CS + Pop DS + Assume DS:Driver + + Mov SI, Offset CreateMsg + Mov BX, 40 + Call SetInfoLine + + Mov AH, 3Ch + Xor CX, CX + Mov DX, Offset Filename + Int 21h + JC WriteError + + Mov BX, AX + Mov FileHandle, BX + Trace "File opened" + +; Write header once + Mov AH, 40h + Mov CX, 22+32 + Mov DX, Offset MIDIHeader + Int 21h + JC WriteError + + Trace "Header written" + +Poll2: + Call WriteMIDIBlock + JC WriteError + +; Update time counters + Mov EAX, FrameTimeError + Mov EBX, FrameTime + Add AccumulatedTimeError, EAX + AdC AccumulatedTime, EBX + + Ret + +WriteError: + Call CheckFileClosed + Mov SI, Offset WriteErrorMsg + Mov BX, 40 + Call SetInfoLine + Call StopPlayback + + Ret + +EndP Poll + Assume DS:Nothing + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far ; Frames per second = 0.4*BX + ; -> Milliseconds per frame = 1000/(0.4/BX) + ; = 2500/BX + PushAD + + Mov EAX, 2500 + And EBX, 0FFFFh + Xor EDX, EDX + Div EBX ; EAX = milliseconds + + Mov CS:FrameTime, EAX + Mov CS:FrameTimeError, EDX + + + PopAD + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + Ret + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load (0 based) +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc LoadSample Far + + StC + Ret + +EndP LoadSample + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release (1 based) +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset MIDScreenList + + ClC + Ret + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far + + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far + + Ret + +EndP SetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +StatusByte DB 0 +CountDown DB 0 + +StatusByteLUT DB 2, 2, 2, 2, 1, 1, 2 +InSysex DW 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc BufferMIDIOutput + + PushAD + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov BX, InSysex + Mov SI, MIDIBufferOffset + + Test BX, BX + JZ BufferMIDINoSysex + + Cmp AL, 0F7h + JNE BufferMIDIOutput1 + + Mov DX, SI + Sub DX, BX ; DX = count of sysex bytes + Mov [BX], DL + Mov InSysex, 0 + + Jmp BufferMIDIOutput1 + +BufferMIDINoSysex: + Cmp Countdown, 0 + JNE BufferMIDIOutput1 + + Cmp AL, 0F0h + JA BufferMIDIOutput2 + +; Delta time required + + Xor EDX, EDX + Mov EBX, AccumulatedTime + Mov CX, 4 + Mov AccumulatedTime, EDX + +DeltaTimeOutput1: + ShL EDX, 8 + Mov DL, BL + Or DL, 80h + ShR EBX, 7 + LoopNZ DeltaTimeOutput1 + ; EDX = output bytes, DL = most signif + +DeltaTimeOutput2: + Mov [SI], DL + Inc SI + ShR EDX, 8 + JNZ DeltaTimeOutput2 + + And Byte Ptr [SI-1], 7Fh + + Xor BX, BX + Xor DL, DL + Test AL, AL + JNS BufferMIDINoStatus + Cmp AL, 0F0h + JE BufferMIDISysex + + Mov StatusByte, AL + Inc DX + Jmp BufferMIDINoStatus + +BufferMIDISysex: + Mov [SI], AL + Inc SI + Mov InSysex, SI + Jmp BufferMIDIOutput1 + +BufferMIDINoStatus: + Mov BL, StatusByte + ShR BX, 4 + Sub BL, 8 + JC BufferMIDIOutput1 + + Add DL, [StatusByteLUT+BX] + Mov Countdown, DL + +BufferMIDIOutput1: + Mov [SI], AL + Inc SI + Dec Countdown + + Mov MIDIBufferOffset, SI + + Cmp SI, Offset MIDIBuffer+200 + JB BufferMIDIOutput2 + Cmp InSysex, 0 + JNE BufferMIDIOutput2 + + Call WriteMIDIBlock + +BufferMIDIOutput2: + Pop DS + PopAD + + Ret + +EndP BufferMIDIOutput + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +InterpretState DB 0 +InterpretType DB 0 + +Proc SendUARTOut Far ; Local interpreter activated with 0F0h 0F0h. + + Mov AH, CS:InterpretState + Cmp AH, 2 + JB SendUARTOut1 + +; In interpreter. + JE SendUARTOut3 + +SendUARTOut4: + Mov CS:InterpretState, 0 + Ret + +SendUARTOut3: + Cmp AL, 2 + JAE SendUARTOut4 + + Mov CS:InterpretType, AL + Jmp SendUARTOutStateInc + +SendUARTOut1: + Cmp AL, 0F0h + JNE SendUARTOut2 + +SendUARTOutStateInc: + Inc CS:InterpretState + Ret + +SendUARTOut2: + Test AH, AH + JZ SendUARTOutEnd + + Push AX + Mov AL, 0F0h + Call BufferMIDIOutput + Pop AX + Mov CS:InterpretState, 0 + +SendUARTOutEnd: + Call BufferMIDIOutput + + Ret + +EndP SendUARTOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 32 ; Maximum number of channels the + ; driver can handle. +StopAfterPlay DW 1 +DefaultChannels DW 32 +DriverFlags DW 1 ; Supports MIDI Out. + + DW 4 Dup (0) + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + DW Offset SendUARTOut + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/MIDIDRV.ASM b/SoundDrivers/MIDIDRV.ASM new file mode 100755 index 0000000..bcc2a53 --- /dev/null +++ b/SoundDrivers/MIDIDRV.ASM @@ -0,0 +1,525 @@ +; +; MIDI MPU401 Driver for Impulse Tracker. +; Accepts MIDI Input, does MIDI output, but does NOT handle samples at all. +; + + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +OldIRQHandler DD 0 +MIDIUpdateTimer DW 0 +MIDIUpdateCount DW 0 +MIDIUpdateFlag DB 0 +MIDIDriverMsg DB "MPU401 or compatible detected", 13 + DB "Address ", 0FDh, "Xh", 0 +MIDIReinitMsg DB "MPU401 reinitialised", 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetUART ; Given DX = port. + + ClI + + Inc DX + + Xor CX, CX + +ResetUART1: + In AL, DX + Test AL, 40h + LoopNZ ResetUART1 + JNZ ResetUARTFailed + + Mov AL, 0FFh + Out DX, AL + + Xor CX, CX + +ResetUART2: + In AL, DX + Test AL, 80h + LoopNZ ResetUART2 + JNZ ResetUARTFailed + + Dec DX + In AL, DX + Inc DX + Cmp AL, 0FEh + JNE ResetUART2 + + Dec DX + + DB 85h + +ResetUARTFailed: + StC + Ret + +EndP ResetUART + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetUARTMode + + Mov DX, CS:BasePort + Inc DX + + Xor CX, CX + +SetUARTMode1: + In AL, DX + Test AL, 40h + LoopNZ SetUARTMode1 + JNZ SetUARTModeFailed + + Mov AL, 3Fh + Out DX, AL + + Xor CX, CX + +SetUARTMode2: + In AL, DX + Test AL, 80h + LoopNZ SetUARTMode2 + JNZ SetUARTModeFailed + + Dec DX + In AL, DX + Inc DX + Cmp AL, 0FEh + JNE SetUARTMode2 + Dec DX + + DB 85h + +SetUARTModeFailed: + StC + StI + Ret + +EndP SetUARTMode + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UARTOut ; AL = byte out + + Push CX + Push DX + Mov DX, CS:Baseport + + Push AX + Xor CX, CX + Inc DX + +UARTOut1: + In AL, DX + Test AL, 40h + LoopNZ UARTOut1 + + Pop AX + JNZ UARTOutEnd + + Dec DX + Out DX, AL + +UARTOutEnd: + Pop DX + Pop CX + + Ret + +EndP UARTOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +InterpretState DB 0 + +Proc SendUARTOut Far ; Local interpreter activated with 0F0h 0F0h. + + Mov AH, CS:InterpretState + Cmp AH, 2 + JB SendUARTOut1 + JE SendUARTOutStateInc + + Mov CS:InterpretState, 0 + +SendUARTOut4: + Ret + +SendUARTOut1: + Cmp AL, 0F0h + JNE SendUARTOut2 + +SendUARTOutStateInc: + Inc CS:InterpretState + Ret + +SendUARTOut2: + Test AH, AH + JZ SendUARTOutEnd + + Push AX + Mov AL, 0F0h + Call UARTOut + Pop AX + Mov CS:InterpretState, 0 + +SendUARTOutEnd: + Call UARTOut + Ret + +EndP SendUARTOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc MIDIIRQHandler + + PushAD + + Mov AX, MIDIUpdateTimer + Add MIDIUpdateCount, AX + JC MIDIIRQHandler1 + + Mov AL, 20h + Out 20h, AL + Jmp MIDIIRQHandler2 + +MIDIIRQHandler1: + PushF + Call [OldIRQHandler] + +MIDIIRQHandler2: + Xor MIDIUpdateFlag, 1 + JZ MIDIIRQHandlerEnd + + Push DS + Push ES + + ClD + + Call SaveEMSPageFrame + Call Update ; Returns DS:SI, CX + +; Have to clear any sample channels playing. +; Kill any active channel + +MIDIIRQHandler3: + Test Byte Ptr [SI], 1 ; Channel on? + JZ MIDIIRQHandler4 + + Mov Word Ptr [SI], 0 + + Test Byte Ptr [SI+3Ah], 80h + JNZ MIDIIRQHandler4 + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Signify channel off + +MIDIIRQHandler4: + Add SI, 128 + Dec CX + JNZ MIDIIRQHandler3 + + Call RestoreEMSPageFrame + + Pop ES + Pop DS + +MIDIIRQHandlerEnd: + PopAD + IRet + +EndP MIDIIRQHandler + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + + Mov AL, 34h + Out 43h, AL + + Xor AX, AX + Mov ES, AX + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset MIDIIRQHandler + Mov [ES:20h], EAX + + Ret + +EndP SetIRQ + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far + + Mov DX, CS:BasePort + Cmp DX, 0FFFFh + JNE DetectCard1 + + Mov DX, 330h + Call ResetUART + JNC DetectCard2 + + Mov DX, 300h + +DetectCard1: + Call ResetUART + +DetectCard2: + Mov CS:BasePort, DX + Mov EAX, 'Jeff' + Ret + +EndP DetectCard + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Xor AX, AX + Mov ES, AX + Mov EAX, [ES:20h] + Mov OldIRQHandler, EAX + Call SetIRQ + + Call SetUARTMode + + Mov SI, Offset MIDIDriverMsg + Mov AX, BasePort + + ClC + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov SI, Offset MIDIReinitMsg + Mov BX, 40 + Call SetInfoLine + + Mov DX, BasePort + Call ResetUART + + Call SetIRQ + Call SetUARTMode + + Ret + +EndP ReInitSound + Assume DS:Nothing + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Mov DX, CS:BasePort + Call ResetUART + + Xor AX, AX + Mov ES, AX + Mov EAX, CS:OldIRQHandler + Mov [ES:20h], EAX + + Xor AL, AL + Out 40h, AL ; Timer IRQ. + Out 40h, AL + + Ret + +EndP UnInitSound + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + ClI + + Call [UARTBufferEmpty] + JC Poll1 + +PollEnd: + StI + Ret + +Poll1: + Mov DX, BasePort + Inc DX + + In AL, DX + Test AL, AL + JS PollEnd + + Dec DX + In AL, DX + + Call [CS:UARTSend] + Jmp Poll + +EndP Poll + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Push AX + Push BX + Push DX + + ; Frames per second = 2 * (0.4*Tempo) + Mov AX, 0C214h + Mov DX, 16h ; Ticks = (1193181/(2*0.4))/Tempo + Div BX + + ; AX contains counter. + Mov CS:MIDIUpdateTimer, AX + + Out 40h, AL ; Timer IRQ. + Mov AL, AH + Out 40h, AL + +SetTempo2: + Pop DX + Pop BX + Pop AX + Ret + +EndP SetTempo + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Xor AX, AX + StC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 64 ; Maximum number of channels the + ; driver can handle. +StopAfterPlay DW 0 +DefaultChannels DW 64 +DriverFlags DW 1 ; Handles MIDI Output + + DW 4 Dup (0) + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SoundCardScreen ; SetMixVolume + DW Offset SoundCardScreen ; SetStereo + + DW Offset SoundCardScreen ; LoadSample + DW Offset SoundCardScreen ; ReleaseSample + DW Offset SoundCardScreen ; ResetMemory + + DW Offset SoundCardScreen ; GetStatus + DW Offset SoundCardScreen ; SoundCardScreen + DW Offset SoundCardScreen ; GetVariable + DW Offset SoundCardScreen ; SetVariable + + DW Offset SendUARTOut + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/MIW.BAT b/SoundDrivers/MIW.BAT new file mode 100755 index 0000000..61058f7 --- /dev/null +++ b/SoundDrivers/MIW.BAT @@ -0,0 +1,4 @@ +tasm /m /uT310 iwdrv +tlink /3 iwdrv +execom iwdrv itiw.drv +copy itiw.drv .. diff --git a/SoundDrivers/MIX.INC b/SoundDrivers/MIX.INC new file mode 100755 index 0000000..d11f1a9 --- /dev/null +++ b/SoundDrivers/MIX.INC @@ -0,0 +1,1014 @@ + + +ERROR EQU CX +DELTAERROR EQU BP +DELTAOFFSET EQU DX +OLDPOSITION EQU [SI+2Ch] +CURRENTPOSITION EQU [SI+4Ch] +CURRENTPOSITIONERROR EQU Word Ptr [SI+48h] +LOOPSTART EQU [SI+40h] +LOOPEND EQU [SI+44h] +STEPVALUE EQU [SI+02h] +; STEPVALUEHIGH EQU Word Ptr [SI+04h] +DIRECTIONFLAG EQU Byte Ptr [SI+0Bh] + +EXTRAOFFSET = MixResolution/8-2 + +IF MIXRESOLUTION GT 16 + RESOLUTIONSHIFT = 2 +ELSE + RESOLUTIONSHIFT = 1 +ENDIF + +IF STEREOENABLED + RESOLUTIONSHIFT = RESOLUTIONSHIFT+1 +ENDIF + +MixBufferOffset DW 0 + +MixBlockSize DW 0 ; Number of bytes to mix + DW 0 ; High order 0 + +PreMixFunction DW 0 +MixFunctionSeparate DW 0 ; Function to separate blocks into 64k + ; chunks. +MixFunctionSeparateBackwards DW 0 ; function to separate blocks into 64k + ; in backwards steps. +MixFunction DW 0 ; Function to mix samples + +LastPage DW 0 + +MemoryType DB 0 +NumPages DB 0 +SampleLocation DW 0 ; Either EMS Handle or Conventional + ; base segment +EMSPageFrame DW 0 + +LoopCounter DW 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc MixNoLoop + + Call [PreMixFunction] + Call PrepareSampleSegment + + Mov EAX, STEPVALUE ; 16.16 value + Mul DWord Ptr [MixBlockSize] ; 16.0 value + ; EDX:EAX = 32.16 value + ShLD EDX, EAX, 16 ; EDX.AX = 32.16 value. + ; EDX.AX = BytesToMix*StepValue + + Xor CX, CX + Mov EBX, LOOPEND + Sub CX, CURRENTPOSITIONERROR + SBB EBX, CURRENTPOSITION ; EBX.CX = (End-CurrentPosition) + JC MixNoLoop3 + + Cmp EDX, EBX + JL MixNoLoop1 + JG MixNoLoop2 + Cmp AX, CX + JB MixNoLoop1 + +MixNoLoop2: + ; Turn off + Mov EDX, EBX + Mov AX, CX + + Mov Word Ptr [SI], 200h + Test Byte Ptr [SI+3Ah], 80h + JNZ MixNoLoop1 + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Signify channel off + +MixNoLoop1: + Jmp [MixFunctionSeparate] + +MixNoLoop3: + Mov Word Ptr [SI], 200h + Test Byte Ptr [SI+3Ah], 80h + JNZ MixNoLoop4 + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Signify channel off + +MixNoLoop4: + Ret + +EndP MixNoLoop + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc MixForwardsLoop + + Call [PreMixFunction] + Call PrepareSampleSegment + +MixForwardsLoopAgain: + Mov EAX, STEPVALUE ; 16.16 value + Mul DWord Ptr [MixBlockSize] ; 16.0 value + ; EDX:EAX = 32.16 value + ShLD EDX, EAX, 16 ; EDX.AX = 32.16 value. + ; EDX.AX = BytesToMix*StepValue + + Xor CX, CX + Mov EBX, LOOPEND + Sub CX, CURRENTPOSITIONERROR + SBB EBX, CURRENTPOSITION ; EBX.CX = (End-CurrentPosition) + JC UpdateMixForwardsLoop + + Cmp EDX, EBX + JL MixForwardsLoop1 + JG MixForwardsLoop2 + Cmp AX, CX + JB MixForwardsLoop1 + +MixForwardsLoop2: + Mov EDX, EBX + Mov AX, CX + + Call [MixFunctionSeparate] + +UpdateMixForwardsLoop: + Mov EAX, CURRENTPOSITION + Xor EDX, EDX + + Mov EBX, LOOPEND + SUB EAX, EBX + SUB EBX, LOOPSTART + JBE MixForwardsLoop3 + + Div EBX + Add EDX, LOOPSTART + Mov CURRENTPOSITION, EDX + +; Cmp EBX, 10000h +; JAE MixForwardsLoop4 + +; Mov AX, STEPVALUEHIGH +; Cmp AX, BX +; JAE MixForwardsLoop5 + +; MixForwardsLoop4: + Cmp MixBlockSize, 0 + JG MixForwardsLoopAgain + +MixForwardsLoop3: + Ret + +; MixForwardsLoop5: +; Xor DX, DX +; Div BX +; Mov STEPVALUEHIGH, DX + +; Cmp MixBlockSize, 0 +; JG MixForwardsLoopAgain + +; Ret + +MixForwardsLoop1: + Jmp [MixFunctionSeparate] + +EndP MixForwardsLoop + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc MixPingPongLoop + + Call [PreMixFunction] + Call PrepareSampleSegment + +MixPingPongLoopAgain: + Mov EAX, STEPVALUE ; 16.16 value + Mul DWord Ptr [MixBlockSize] ; 16.0 value + ; EDX:EAX = 32.16 value + ShLD EDX, EAX, 16 ; EDX.AX = 32.16 value. + ; EDX.AX = BytesToMix*StepValue + + Cmp DIRECTIONFLAG, 0 + JNE MixPingPongLoopBackwards1 + +MixPingPongLoopForwards1: + Xor CX, CX + Mov EBX, LOOPEND + Sub CX, CURRENTPOSITIONERROR + SBB EBX, CURRENTPOSITION ; EBX.CX = (End-CurrentPosition) + JC UpdateMixPingPongLoopForwards1 + + Cmp EDX, EBX + JG MixPingPongLoopForwards3 + JL MixPingPongLoopForwards2 + + Cmp AX, CX + JAE MixPingPongLoopForwards3 + +MixPingPongLoopForwards2: + Jmp [MixFunctionSeparate] + +MixPingPongLoopForwards3: + Mov EDX, EBX + Mov AX, CX + Call [MixFunctionSeparate] + +UpdateMixPingPongLoopForwards1: + Mov EAX, CURRENTPOSITION + Mov EBX, LOOPEND + Xor EDX, EDX + Sub EAX, EBX + Sub EBX, LOOPSTART + JBE MixPingPongError + + Add EBX, EBX + Div EBX + + ShR EBX, 1 + + Cmp EDX, EBX + JAE MixPingPongLoopForwards4 + + Mov DIRECTIONFLAG, 1 + Mov EAX, LOOPEND + Sub EAX, EDX + Dec EAX + Mov CURRENTPOSITION, EAX + Neg Word Ptr CURRENTPOSITIONERROR + Jmp MixPingPongLoopNext + +MixPingPongLoopForwards4: + Sub EDX, EBX + Add EDX, LOOPSTART + Mov CURRENTPOSITION, EDX + Jmp MixPingPongLoopNext + +MixPingPongLoopBackwards1: + Mov EBX, CURRENTPOSITION + Mov CX, CURRENTPOSITIONERROR + + Sub CX, 0FFFFh + SBB EBX, LOOPSTART + JC UpdateMixPingPongLoopBackwards1 + + Cmp EDX, EBX + JG MixPingPongLoopBackwards3 + JL MixPingPongLoopBackwards2 + + Cmp AX, CX + JAE MixPingPongLoopBackwards3 + +MixPingPongLoopBackwards2: + Call [MixFunctionSeparateBackwards] + +MixPingPongError: + Ret + +MixPingPongLoopBackwards3: + Mov EDX, EBX + Mov AX, CX + Call [MixFunctionSeparateBackwards] + +UpdateMixPingPongLoopBackwards1: + Mov EBX, LOOPEND + Mov EAX, LOOPSTART + Sub EBX, EAX + JBE MixPingPongError + + Sub EAX, CURRENTPOSITION + Xor EDX, EDX + Add EBX, EBX + Div EBX + + ShR EBX, 1 + + Cmp EDX, EBX + JAE MixPingPongLoopBackwards4 + + Mov DIRECTIONFLAG, 0 + Add EDX, LOOPSTART + Mov CURRENTPOSITION, EDX + Neg Word Ptr CURRENTPOSITIONERROR + Jmp MixPingPongLoopNext + +MixPingPongLoopBackwards4: + Sub EBX, EDX + Add EBX, LOOPEND + Dec EBX + Mov CURRENTPOSITION, EBX + +MixPingPongLoopNext: + Cmp MixBlockSize, 0 + JG MixPingPongLoopAgain + + Ret + +EndP MixPingPongLoop + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UpdateNoLoop + + Mov EAX, STEPVALUE ; 16.16 value + Mul DWord Ptr [MixBlockSize] ; 16.0 value + ; EDX:EAX = 32.16 value + ShLD EDX, EAX, 16 ; EDX.AX = 32.16 value. + ; EDX.AX = BytesToMix*StepValue + Add CURRENTPOSITIONERROR, AX + AdC EDX, CURRENTPOSITION + + Cmp EDX, LOOPEND + JL UpdateNoLoop1 + +UpdateNoLoop2: ; Turn off + Mov Word Ptr [SI], 200h + + Test Byte Ptr [SI+3Ah], 80h + JNZ UpdateNoLoop1 + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Signify channel off + Ret + +UpdateNoLoop1: + Mov CURRENTPOSITION, EDX + + Ret + +EndP UpdateNoLoop + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UpdateForwardsLoop + + Mov EAX, STEPVALUE ; 16.16 value + Mul DWord Ptr [MixBlockSize] ; 16.0 value + ; EDX:EAX = 32.16 value + ShLD EDX, EAX, 16 ; EDX.AX = 32.16 value. + ; EDX.AX = BytesToMix*StepValue + Add CURRENTPOSITIONERROR, AX + AdC EDX, CURRENTPOSITION + + Cmp EDX, LOOPEND + JL UpdateForwardsLoop1 + +UpdateForwardsLoop2: ; Reset position... + Mov EBX, LOOPEND + Mov EAX, EDX + Xor EDX, EDX + Sub EAX, EBX + Sub EBX, LOOPSTART + JZ UpdateForwardsLoop1 + Div EBX + + Add EDX, LOOPSTART + +UpdateForwardsLoop1: + Mov CURRENTPOSITION, EDX + Ret + +EndP UpdateForwardsLoop + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UpdatePingPongLoop + + Mov EAX, STEPVALUE ; 16.16 value + Mul DWord Ptr [MixBlockSize] ; 16.0 value + ; EDX:EAX = 32.16 value + ShLD EDX, EAX, 16 ; EDX.AX = 32.16 value. + ; EDX.AX = BytesToMix*StepValue + + Cmp DIRECTIONFLAG, 0 + JNE UpdatePingPongLoopBackwards1 + +UpdatePingPongLoopForwards1: + Add CURRENTPOSITIONERROR, AX + AdC EDX, CURRENTPOSITION + + Cmp EDX, LOOPEND + JA UpdatePingPongLoopForwards2 + + Mov CURRENTPOSITION, EDX + Ret + +UpdatePingPongLoopForwards2: + Mov EAX, EDX + Mov EBX, LOOPEND + Xor EDX, EDX + Sub EAX, EBX + Sub EBX, LOOPSTART + Add EBX, EBX + Div EBX + + ShR EBX, 1 + + Cmp EDX, EBX + JAE UpdatePingPongLoopForwards3 + + Mov DIRECTIONFLAG, 1 + Mov EAX, LOOPEND + Sub EAX, EDX + Dec EAX + NEG CURRENTPOSITIONERROR + Mov CURRENTPOSITION, EAX + Ret + +UpdatePingPongLoopForwards3: + Sub EDX, EBX + Add EDX, LOOPSTART + Mov CURRENTPOSITION, EDX + Ret + +UpdatePingPongLoopBackwards1: + Sub CURRENTPOSITIONERROR, AX + Mov ECX, CURRENTPOSITION + SBB ECX, EDX + + Cmp ECX, LOOPSTART + JLE UpdatePingPongLoopBackwards2 + + Mov CURRENTPOSITION, ECX + Ret + +UpdatePingPongLoopBackwards2: + Mov EAX, LOOPSTART + Mov EBX, LOOPEND + Xor EDX, EDX + Sub EBX, EAX + Sub EAX, ECX + Add EBX, EBX + Div EBX + + ShR EBX, 1 + + Cmp EDX, EBX + JAE UpdatePingPongLoopBackwards3 + + Mov DIRECTIONFLAG, 0 + Add EDX, LOOPSTART + NEG CURRENTPOSITIONERROR + Mov CURRENTPOSITION, EDX + Ret + +UpdatePingPongLoopBackwards3: + Sub EBX, EDX + Add EBX, LOOPEND + Dec EBX + Mov CURRENTPOSITION, EBX + + Ret + +EndP UpdatePingPongLoop + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PrepareSampleSegment ; Sets up sample mixing segment + + Mov ES, SongDataArea + + Mov BX, [SI+34h] + Mov EAX, [ES:BX+48h] + + Mov DWord Ptr MemoryType, EAX ; Writes numpages & Sample + ; location also. + Mov LastPage, 0FFFFh + + Ret + +EndP PrepareSampleSegment + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetSampleSegment ; Given EDI, Returns ES + + Mov CX, Word Ptr CS:MemoryType + + Cmp CL, 2 + JNE SetSampleSegment1 + + Push EAX + Push EDX + + Mov EBX, EDI + ShR EBX, 14 + And EDI, 16383 + + Cmp BX, LastPage + JE SetSampleEMS2 + + Mov LastPage, BX + Mov DX, SampleLocation ; EMS handle + ; BX = starting page required + Mov AL, 3 + Add BX, 3 + + Cmp BL, CH + JBE SetSampleEMS1 + + Sub CH, BL + Add BL, CH + Add AL, CH + JNC SetSampleEMS2 + +SetSampleEMS1: + Mov AH, 44h + Int 67h + + Dec BX + Dec AL + JNS SetSampleEMS1 + +SetSampleEMS2: + Mov ES, EMSPageFrame + + Pop EDX + Pop EAX + + Ret + +SetSampleSegment1: ; Conventional memory + Mov ECX, EDI + And EDI, 15 + ShR ECX, 4 + Add CX, SampleLocation + Mov ES, CX + + Ret + +EndP SetSampleSegment + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetBackSampleSegment ; Given BX = frame, Returns ES + + Mov CX, Word Ptr CS:MemoryType + + Cmp CL, 2 + JNE SetBackSampleSegment1 + + Push EAX + Push EDX + + Cmp BX, LastPage + JE SetBackSampleEMS2 + + Mov LastPage, BX + Mov DX, SampleLocation ; EMS handle + ; BX = starting page required + Mov AL, 3 + Add BX, 3 + + Cmp BL, CH + JBE SetBackSampleEMS1 + + Sub CH, BL + Add BL, CH + Add AL, CH + JNC SetBackSampleEMS2 + +SetBackSampleEMS1: + Mov AH, 44h + Int 67h + + Dec BX + Dec AL + JNS SetBackSampleEMS1 + +SetBackSampleEMS2: + Mov ES, EMSPageFrame + + Pop EDX + Pop EAX + + Ret + +SetBackSampleSegment1: ; Conventional memory + ShL BX, 10 + Add BX, SampleLocation + Mov ES, BX + + Ret + +EndP SetBackSampleSegment + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc MFS8Bit ; EDX:AX = 32.16 bytes offset. + ; to mix + + + Push AX + Push EDX + + Mov EDI, CURRENTPOSITION + Call SetSampleSegment + + Xor CX, CX ; EDI = CurrentPosition & (2^14-1) + + Mov EBX, 0FFFEh + + Sub CX, CURRENTPOSITIONERROR + SBB EBX, EDI + ; EBX:CX = 64k-(CurrentPosition & (2^14-1)) + ; EDX:AX = blocksize + Cmp EDX, EBX + JBE MFS8Bit1 + + Mov EDX, EBX + Mov AX, CX + +MFS8Bit1: + ; Now to calculate bytes to mix... + ShL EAX, 16 + SHRD EAX, EDX, 16 + ShR EDX, 16 ; EDX:EAX = (16)32.16 offset + + Mov EBX, STEPVALUE + Cmp EDX, EBX + JAE MFS8Bit2 + + Div EBX + Add EDX, 0FFFFFFFFh + AdC EAX, 0 ; EAX = no of bytes to mix + JZ MFS8Bit2 + + Push EAX + + Xor ECX, ECX + Mov DELTAOFFSET, [SI+4] ; Stepvalue + Mov DELTAERROR, [SI+2] ; Stepvalue + Mov CX, CURRENTPOSITIONERROR + + Push DS + Push SI + + Mov SI, MixBufferOffset + Mov DS, MixSegment + Call [MixFunction] + + Pop SI + Pop DS + Pop ECX + Jmp MFS8Bit3 + +MFS8Bit2: +; Xor ECX, ECX + Pop EDX + Pop AX + + Ret + +MFS8Bit3: + ; Update pointers... + Mov EAX, STEPVALUE + Mul ECX + + Sub MixBlockSize, CX + ShL CX, RESOLUTIONSHIFT + Add MixBufferOffset, CX + + ; EDX:EAX = offset mixed (32.16) + ShLD EDX, EAX, 16 + Mov BX, AX + Mov ECX, EDX ; ECX:BX = offset mixed + + Add CURRENTPOSITIONERROR, BX + AdC CURRENTPOSITION, ECX + + Pop EDX + Pop AX + + Sub AX, BX + SBB EDX, ECX + + JG MFS8Bit + + Ret + +EndP MFS8Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc MFS16Bit + + Push AX + Push EDX + + Mov EDI, CURRENTPOSITION + Add EDI, EDI + Call SetSampleSegment + + ShR EDI, 1 ; EDI = number of samples. + + Xor CX, CX + + Mov EBX, 7FFEh + + Sub CX, CURRENTPOSITIONERROR + SBB EBX, EDI + + Cmp EDX, EBX + JBE MFS16Bit1 + + Mov EDX, EBX + Mov AX, CX + +MFS16Bit1: + ; Now to calculate bytes to mix... + ShL EAX, 16 + SHRD EAX, EDX, 16 + ShR EDX, 16 ; EDX:EAX = (16)32.16 offset + + Mov EBX, STEPVALUE + Cmp EDX, EBX + JAE MFS16Bit2 + + Div EBX + Add EDX, 0FFFFFFFFh + AdC EAX, 0 ; EAX = no of bytes to mix + JZ MFS16Bit2 + + Push EAX + + Xor ECX, ECX + Mov DELTAOFFSET, [SI+4] ; Stepvalue + Mov DELTAERROR, [SI+2] ; Stepvalue + Mov CX, CURRENTPOSITIONERROR + + Push DS + Push SI + + Mov SI, MixBufferOffset + Mov DS, MixSegment + Call [MixFunction] + + Pop SI + Pop DS + Pop ECX + Jmp MFS16Bit3 + +MFS16Bit2: +; Xor ECX, ECX + Pop EDX + Pop AX + Ret + +MFS16Bit3: + ; Update pointers... + Mov EAX, STEPVALUE + Mul ECX + + Sub MixBlockSize, CX + ShL CX, RESOLUTIONSHIFT + Add MixBufferOffset, CX + + ; EDX:EAX = offset mixed (32.16) + ShLD EDX, EAX, 16 + Mov BX, AX + Mov ECX, EDX ; ECX:BX = offset mixed + + Add CURRENTPOSITIONERROR, BX + AdC CURRENTPOSITION, ECX + + Pop EDX + Pop AX + + Sub AX, BX + SBB EDX, ECX + + JG MFS16Bit + + Ret + +EndP MFS16Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc MBS8Bit + + Push AX + Push EDX ; EDX:AX = 32.16 blocksize + + Mov EDI, CURRENTPOSITION + Mov EBX, EDI + Add EBX, 2 + ShR EBX, 14 ; BX = frame + + Sub BX, 3 + JNC MBS8Bit4 + + Xor BX, BX + +MBS8Bit4: + Mov ECX, EBX + ShL ECX, 14 + Sub EDI, ECX + + Call SetBackSampleSegment + + Mov ECX, CURRENTPOSITION + Mov BX, CURRENTPOSITIONERROR + And ECX, 16383 + Add ECX, 0BFFEh + Cmp ECX, EDX + JG MBS8Bit1 + JL MBS8Bit5 + Cmp BX, AX + JG MBS8Bit1 + +MBS8Bit5: + Mov EDX, ECX + Mov AX, BX + +MBS8Bit1: + + ; Now to calculate bytes to mix... + ShL EAX, 16 + SHRD EAX, EDX, 16 + ShR EDX, 16 ; EDX:EAX = (16)32.16 offset + + Mov EBX, STEPVALUE + Cmp EDX, EBX + JAE MBS8Bit2 + + Div EBX + Add EDX, 0FFFFFFFFh + AdC EAX, 0 ; EAX = no of bytes to mix + JZ MBS8Bit2 + + Push EAX + + Xor ECX, ECX + Mov EBP, [SI+2] ; Stepvalue + Neg EBP + ShLD EDX, EBP, 16 + + Mov CX, CURRENTPOSITIONERROR + + Push DS + Push SI + + Mov SI, MixBufferOffset + Mov DS, MixSegment + Call [MixFunction] + + Pop SI + Pop DS + Pop ECX + Jmp MBS8Bit3 + +MBS8Bit2: +; Xor ECX, ECX + Pop EDX + Pop AX + Ret + +MBS8Bit3: + ; Update pointers... + Mov EAX, STEPVALUE + Mul ECX + + Sub MixBlockSize, CX + ShL CX, RESOLUTIONSHIFT + Add MixBufferOffset, CX + + ; EDX:EAX = offset mixed (32.16) + ShLD EDX, EAX, 16 + Mov BX, AX + Mov ECX, EDX ; ECX:BX = offset mixed + + Sub CURRENTPOSITIONERROR, BX + SBB CURRENTPOSITION, ECX + + Pop EDX + Pop AX + + Sub AX, BX + SBB EDX, ECX + + JG MBS8Bit + + Ret + +EndP MBS8Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc MBS16Bit + + Push AX + Push EDX ; EDX:AX = 32.16 blocksize + + Mov EDI, CURRENTPOSITION + Mov EBX, EDI + Add EBX, 4 + ShR EBX, 13 ; BX = frame + + Sub BX, 3 + JNC MBS16Bit4 + + Xor BX, BX + +MBS16Bit4: + Mov ECX, EBX + ShL ECX, 13 + Sub EDI, ECX + + Call SetBackSampleSegment + + Mov ECX, CURRENTPOSITION + Mov BX, CURRENTPOSITIONERROR + And ECX, 8191 + Add ECX, 05FFEh + Cmp ECX, EDX + JG MBS16Bit1 + JL MBS16Bit5 + Cmp BX, AX + JG MBS16Bit1 + +MBS16Bit5: + Mov EDX, ECX + Mov AX, BX + +MBS16Bit1: + + ; Now to calculate bytes to mix... + ShL EAX, 16 + SHRD EAX, EDX, 16 + ShR EDX, 16 ; EDX:EAX = (16)32.16 offset + + Mov EBX, STEPVALUE + Cmp EDX, EBX + JAE MBS16Bit2 + + Div EBX + Add EDX, 0FFFFFFFFh + AdC EAX, 0 ; EAX = no of bytes to mix + JZ MBS16Bit2 + + Push EAX + + Xor ECX, ECX + Mov EBP, [SI+2] ; Stepvalue + Neg EBP + ShLD EDX, EBP, 16 + + Mov CX, CURRENTPOSITIONERROR + + Push DS + Push SI + + Mov SI, MixBufferOffset + Mov DS, MixSegment + Call [MixFunction] + + Pop SI + Pop DS + Pop ECX + Jmp MBS16Bit3 + +MBS16Bit2: +; Xor ECX, ECX + Pop EDX + Pop AX + Ret + +MBS16Bit3: + ; Update pointers... + Mov EAX, STEPVALUE + Mul ECX + + Sub MixBlockSize, CX + ShL CX, RESOLUTIONSHIFT + Add MixBufferOffset, CX + + ; EDX:EAX = offset mixed (32.16) + ShLD EDX, EAX, 16 + Mov BX, AX + Mov ECX, EDX ; ECX:BX = offset mixed + + Sub CURRENTPOSITIONERROR, BX + SBB CURRENTPOSITION, ECX + + Pop EDX + Pop AX + + Sub AX, BX + SBB EDX, ECX + + JG MBS16Bit + + Ret + +EndP MBS16Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReportError + + Ret + +EndP ReportError + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + diff --git a/SoundDrivers/MIXING.TXT b/SoundDrivers/MIXING.TXT new file mode 100755 index 0000000..62e5567 --- /dev/null +++ b/SoundDrivers/MIXING.TXT @@ -0,0 +1,21 @@ +Mixing: + +General principles + +Mix 8->16 samples at once. If you have to mix an odd number, jump into the +table at an offset + +Instructions: + + Add , + Mov AL, [ESI] + AdC ESI, + Mov EDX, [EDI] + Mov EBP, [EDI+4] + Mov EBX, [EAX] + Mov ECX, [EAX+] + Add EDX, EBX + Add EBP, ECX + Mov [EDI], EDX + Mov [EDI+4], EBP + diff --git a/SoundDrivers/MIXWAV.INC b/SoundDrivers/MIXWAV.INC new file mode 100755 index 0000000..cb2045e --- /dev/null +++ b/SoundDrivers/MIXWAV.INC @@ -0,0 +1,1065 @@ + + +ERROR EQU CX +DELTAERROR EQU BP +DELTAOFFSET EQU DX +OLDPOSITION EQU [SI+2Ch] +CURRENTPOSITION EQU [SI+4Ch] +CURRENTPOSITIONERROR EQU Word Ptr [SI+48h] +LOOPSTART EQU [SI+40h] +LOOPEND EQU [SI+44h] +STEPVALUE EQU [SI+02h] +; STEPVALUEHIGH EQU Word Ptr [SI+04h] +DIRECTIONFLAG EQU Byte Ptr [SI+0Bh] + +EXTRAOFFSET = MixResolution/8-2 + +IF MIXRESOLUTION GT 16 + RESOLUTIONSHIFT = 2 +ELSE + RESOLUTIONSHIFT = 1 +ENDIF + +IF STEREOENABLED + RESOLUTIONSHIFT = RESOLUTIONSHIFT+1 +ENDIF + +MixBufferOffset DW 0 + +MixBlockSize DW 0 ; Number of bytes to mix + DW 0 ; High order 0 + +PreMixFunction DW 0 +MixFunctionSeparate DW 0 ; Function to separate blocks into 64k + ; chunks. +MixFunctionSeparateBackwards DW 0 ; function to separate blocks into 64k + ; in backwards steps. +MixFunction DW 0 ; Function to mix samples + +LastPage DW 0 + +MemoryType DB 0 +NumPages DB 0 +SampleLocation DW 0 ; Either EMS Handle or Conventional + ; base segment +EMSPageFrame DW 0 + +LoopCounter DW 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc MixNoLoop + + Call [PreMixFunction] + Call PrepareSampleSegment + + Mov EAX, STEPVALUE ; 16.16 value + Mul DWord Ptr [MixBlockSize] ; 16.0 value + ; EDX:EAX = 32.16 value + ShLD EDX, EAX, 16 ; EDX.AX = 32.16 value. + ; EDX.AX = BytesToMix*StepValue + + Xor CX, CX + Mov EBX, LOOPEND + Sub CX, CURRENTPOSITIONERROR + SBB EBX, CURRENTPOSITION ; EBX.CX = (End-CurrentPosition) + JC MixNoLoopEnd + + Cmp EDX, EBX + JL MixNoLoop1 + JG MixNoLoop2 + Cmp AX, CX + JAE MixNoLoop2 + +MixNoLoop1: + Jmp [MixFunctionSeparate] + +MixNoLoop2: ; Turn off + Mov EDX, EBX + Mov AX, CX + + Call [MixFunctionSeparate] + +MixNoLoop3: + Mov Word Ptr [SI], 200h + Test Byte Ptr [SI+3Ah], 80h + JNZ MixNoLoop4 + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Signify channel off + +MixNoLoop4: + PushAD + Push DS + + Mov EDX, CS:LastLeftValue + Mov EDI, CS:LastRightValue + +IF USECLICKFADETHRESHHOLD + Cmp EDX, CLICKFADETHRESHHOLD + JBE NoClickRemovalLeft + + Xor EDX, EDX + +NoClickRemovalLeft: + Cmp EDI, CLICKFADETHRESHHOLD + JBE NoClickRemovalRight + + Xor EDI, EDI + +NoClickRemovalRight: +ENDIF + Neg EDX + Neg EDI + + Mov CX, CS:MixBlockSize + Mov SI, CS:MixBufferOffset + Mov DS, CS:MixSegment + JCXZ MixNoLoopClickRemovalEnd + +MixNoLoopClickRemoval1: + Mov EAX, EDX + Mov EBX, EDI + + Add [SI], EDX + Add [SI+4], EDI + + SAR EAX, 12 + SAR EBX, 12 + + Sub EAX, 1 + AdC EAX, 1 + Sub EBX, 1 + AdC EBX, 1 + + Sub EDX, EAX + Sub EDI, EBX + + Add SI, 8 + Loop MixNoLoopClickRemoval1 + +MixNoLoopClickRemovalEnd: + Add CS:LastClickRemovalLeft, EDX + Add CS:LastClickRemovalRight, EDI + + Pop DS + PopAD + +MixNoLoopEnd: + Ret + +EndP MixNoLoop + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc MixForwardsLoop + + Call [PreMixFunction] + Call PrepareSampleSegment + +MixForwardsLoopAgain: + Mov EAX, STEPVALUE ; 16.16 value + Mul DWord Ptr [MixBlockSize] ; 16.0 value + ; EDX:EAX = 32.16 value + ShLD EDX, EAX, 16 ; EDX.AX = 32.16 value. + ; EDX.AX = BytesToMix*StepValue + + Xor CX, CX + Mov EBX, LOOPEND + Sub CX, CURRENTPOSITIONERROR + SBB EBX, CURRENTPOSITION ; EBX.CX = (End-CurrentPosition) + JC UpdateMixForwardsLoop + + Cmp EDX, EBX + JL MixForwardsLoop1 + JG MixForwardsLoop2 + Cmp AX, CX + JB MixForwardsLoop1 + +MixForwardsLoop2: + Mov EDX, EBX + Mov AX, CX + + Call [MixFunctionSeparate] + +UpdateMixForwardsLoop: + Mov EAX, CURRENTPOSITION + Xor EDX, EDX + + Mov EBX, LOOPEND + SUB EAX, EBX + SUB EBX, LOOPSTART + JBE MixForwardsLoop3 + + Div EBX + Add EDX, LOOPSTART + Mov CURRENTPOSITION, EDX + +; Cmp EBX, 10000h +; JAE MixForwardsLoop4 + +; Mov AX, STEPVALUEHIGH +; Cmp AX, BX +; JAE MixForwardsLoop5 + +; MixForwardsLoop4: + Cmp MixBlockSize, 0 + JG MixForwardsLoopAgain + +MixForwardsLoop3: + Ret + +; MixForwardsLoop5: +; Xor DX, DX +; Div BX +; Mov STEPVALUEHIGH, DX + +; Cmp MixBlockSize, 0 +; JG MixForwardsLoopAgain + +; Ret + +MixForwardsLoop1: + Jmp [MixFunctionSeparate] + +EndP MixForwardsLoop + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc MixPingPongLoop + + Call [PreMixFunction] + Call PrepareSampleSegment + +MixPingPongLoopAgain: + Mov EAX, STEPVALUE ; 16.16 value + Mul DWord Ptr [MixBlockSize] ; 16.0 value + ; EDX:EAX = 32.16 value + ShLD EDX, EAX, 16 ; EDX.AX = 32.16 value. + ; EDX.AX = BytesToMix*StepValue + + Cmp DIRECTIONFLAG, 0 + JNE MixPingPongLoopBackwards1 + +MixPingPongLoopForwards1: + Xor CX, CX + Mov EBX, LOOPEND + Sub CX, CURRENTPOSITIONERROR + SBB EBX, CURRENTPOSITION ; EBX.CX = (End-CurrentPosition) + JC UpdateMixPingPongLoopForwards1 + + Cmp EDX, EBX + JG MixPingPongLoopForwards3 + JL MixPingPongLoopForwards2 + + Cmp AX, CX + JAE MixPingPongLoopForwards3 + +MixPingPongLoopForwards2: + Jmp [MixFunctionSeparate] + +MixPingPongLoopForwards3: + Mov EDX, EBX + Mov AX, CX + Call [MixFunctionSeparate] + +UpdateMixPingPongLoopForwards1: + Mov EAX, CURRENTPOSITION + Mov EBX, LOOPEND + Xor EDX, EDX + Sub EAX, EBX + Sub EBX, LOOPSTART + JBE MixPingPongError + + Add EBX, EBX + Div EBX + + ShR EBX, 1 + + Cmp EDX, EBX + JAE MixPingPongLoopForwards4 + + Mov DIRECTIONFLAG, 1 + Mov EAX, LOOPEND + Sub EAX, EDX + Dec EAX + Mov CURRENTPOSITION, EAX + Neg Word Ptr CURRENTPOSITIONERROR + Jmp MixPingPongLoopNext + +MixPingPongLoopForwards4: + Sub EDX, EBX + Add EDX, LOOPSTART + Mov CURRENTPOSITION, EDX + Jmp MixPingPongLoopNext + +MixPingPongLoopBackwards1: + Mov EBX, CURRENTPOSITION + Mov CX, CURRENTPOSITIONERROR + + Sub CX, 0FFFFh + SBB EBX, LOOPSTART + JC UpdateMixPingPongLoopBackwards1 + + Cmp EDX, EBX + JG MixPingPongLoopBackwards3 + JL MixPingPongLoopBackwards2 + + Cmp AX, CX + JAE MixPingPongLoopBackwards3 + +MixPingPongLoopBackwards2: + Call [MixFunctionSeparateBackwards] + +MixPingPongError: + Ret + +MixPingPongLoopBackwards3: + Mov EDX, EBX + Mov AX, CX + Call [MixFunctionSeparateBackwards] + +UpdateMixPingPongLoopBackwards1: + Mov EBX, LOOPEND + Mov EAX, LOOPSTART + Sub EBX, EAX + JBE MixPingPongError + + Sub EAX, CURRENTPOSITION + Xor EDX, EDX + Add EBX, EBX + Div EBX + + ShR EBX, 1 + + Cmp EDX, EBX + JAE MixPingPongLoopBackwards4 + + Mov DIRECTIONFLAG, 0 + Add EDX, LOOPSTART + Mov CURRENTPOSITION, EDX + Neg Word Ptr CURRENTPOSITIONERROR + Jmp MixPingPongLoopNext + +MixPingPongLoopBackwards4: + Sub EBX, EDX + Add EBX, LOOPEND + Dec EBX + Mov CURRENTPOSITION, EBX + +MixPingPongLoopNext: + Cmp MixBlockSize, 0 + JG MixPingPongLoopAgain + + Ret + +EndP MixPingPongLoop + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UpdateNoLoop + + Mov EAX, STEPVALUE ; 16.16 value + Mul DWord Ptr [MixBlockSize] ; 16.0 value + ; EDX:EAX = 32.16 value + ShLD EDX, EAX, 16 ; EDX.AX = 32.16 value. + ; EDX.AX = BytesToMix*StepValue + Add CURRENTPOSITIONERROR, AX + AdC EDX, CURRENTPOSITION + + Cmp EDX, LOOPEND + JL UpdateNoLoop1 + +UpdateNoLoop2: ; Turn off + Mov Word Ptr [SI], 200h + + Test Byte Ptr [SI+3Ah], 80h + JNZ UpdateNoLoop1 + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Signify channel off + Ret + +UpdateNoLoop1: + Mov CURRENTPOSITION, EDX + + Ret + +EndP UpdateNoLoop + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UpdateForwardsLoop + + Mov EAX, STEPVALUE ; 16.16 value + Mul DWord Ptr [MixBlockSize] ; 16.0 value + ; EDX:EAX = 32.16 value + ShLD EDX, EAX, 16 ; EDX.AX = 32.16 value. + ; EDX.AX = BytesToMix*StepValue + Add CURRENTPOSITIONERROR, AX + AdC EDX, CURRENTPOSITION + + Cmp EDX, LOOPEND + JL UpdateForwardsLoop1 + +UpdateForwardsLoop2: ; Reset position... + Mov EBX, LOOPEND + Mov EAX, EDX + Xor EDX, EDX + Sub EAX, EBX + Sub EBX, LOOPSTART + JZ UpdateForwardsLoop1 + Div EBX + + Add EDX, LOOPSTART + +UpdateForwardsLoop1: + Mov CURRENTPOSITION, EDX + Ret + +EndP UpdateForwardsLoop + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UpdatePingPongLoop + + Mov EAX, STEPVALUE ; 16.16 value + Mul DWord Ptr [MixBlockSize] ; 16.0 value + ; EDX:EAX = 32.16 value + ShLD EDX, EAX, 16 ; EDX.AX = 32.16 value. + ; EDX.AX = BytesToMix*StepValue + + Cmp DIRECTIONFLAG, 0 + JNE UpdatePingPongLoopBackwards1 + +UpdatePingPongLoopForwards1: + Add CURRENTPOSITIONERROR, AX + AdC EDX, CURRENTPOSITION + + Cmp EDX, LOOPEND + JA UpdatePingPongLoopForwards2 + + Mov CURRENTPOSITION, EDX + Ret + +UpdatePingPongLoopForwards2: + Mov EAX, EDX + Mov EBX, LOOPEND + Xor EDX, EDX + Sub EAX, EBX + Sub EBX, LOOPSTART + Add EBX, EBX + Div EBX + + ShR EBX, 1 + + Cmp EDX, EBX + JAE UpdatePingPongLoopForwards3 + + Mov DIRECTIONFLAG, 1 + Mov EAX, LOOPEND + Sub EAX, EDX + Dec EAX + NEG CURRENTPOSITIONERROR + Mov CURRENTPOSITION, EAX + Ret + +UpdatePingPongLoopForwards3: + Sub EDX, EBX + Add EDX, LOOPSTART + Mov CURRENTPOSITION, EDX + Ret + +UpdatePingPongLoopBackwards1: + Sub CURRENTPOSITIONERROR, AX + Mov ECX, CURRENTPOSITION + SBB ECX, EDX + + Cmp ECX, LOOPSTART + JLE UpdatePingPongLoopBackwards2 + + Mov CURRENTPOSITION, ECX + Ret + +UpdatePingPongLoopBackwards2: + Mov EAX, LOOPSTART + Mov EBX, LOOPEND + Xor EDX, EDX + Sub EBX, EAX + Sub EAX, ECX + Add EBX, EBX + Div EBX + + ShR EBX, 1 + + Cmp EDX, EBX + JAE UpdatePingPongLoopBackwards3 + + Mov DIRECTIONFLAG, 0 + Add EDX, LOOPSTART + NEG CURRENTPOSITIONERROR + Mov CURRENTPOSITION, EDX + Ret + +UpdatePingPongLoopBackwards3: + Sub EBX, EDX + Add EBX, LOOPEND + Dec EBX + Mov CURRENTPOSITION, EBX + + Ret + +EndP UpdatePingPongLoop + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PrepareSampleSegment ; Sets up sample mixing segment + + Mov ES, SongDataArea + + Mov BX, [SI+34h] + Mov EAX, [ES:BX+48h] + + Mov DWord Ptr MemoryType, EAX ; Writes numpages & Sample + ; location also. + Mov LastPage, 0FFFFh + + Ret + +EndP PrepareSampleSegment + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetSampleSegment ; Given EDI, Returns ES + + Mov CX, Word Ptr CS:MemoryType + + Cmp CL, 2 + JNE SetSampleSegment1 + + Push EAX + Push EDX + + Mov EBX, EDI + ShR EBX, 14 + And EDI, 16383 + + Cmp BX, LastPage + JE SetSampleEMS2 + + Mov LastPage, BX + Mov DX, SampleLocation ; EMS handle + ; BX = starting page required + Mov AL, 3 + Add BX, 3 + + Cmp BL, CH + JBE SetSampleEMS1 + + Sub CH, BL + Add BL, CH + Add AL, CH + JNC SetSampleEMS2 + +SetSampleEMS1: + Mov AH, 44h + Int 67h + + Dec BX + Dec AL + JNS SetSampleEMS1 + +SetSampleEMS2: + Mov ES, EMSPageFrame + + Pop EDX + Pop EAX + + Ret + +SetSampleSegment1: ; Conventional memory + Mov ECX, EDI + And EDI, 15 + ShR ECX, 4 + Add CX, SampleLocation + Mov ES, CX + + Ret + +EndP SetSampleSegment + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetBackSampleSegment ; Given BX = frame, Returns ES + + Mov CX, Word Ptr CS:MemoryType + + Cmp CL, 2 + JNE SetBackSampleSegment1 + + Push EAX + Push EDX + + Cmp BX, LastPage + JE SetBackSampleEMS2 + + Mov LastPage, BX + Mov DX, SampleLocation ; EMS handle + ; BX = starting page required + Mov AL, 3 + Add BX, 3 + + Cmp BL, CH + JBE SetBackSampleEMS1 + + Sub CH, BL + Add BL, CH + Add AL, CH + JNC SetBackSampleEMS2 + +SetBackSampleEMS1: + Mov AH, 44h + Int 67h + + Dec BX + Dec AL + JNS SetBackSampleEMS1 + +SetBackSampleEMS2: + Mov ES, EMSPageFrame + + Pop EDX + Pop EAX + + Ret + +SetBackSampleSegment1: ; Conventional memory + ShL BX, 10 + Add BX, SampleLocation + Mov ES, BX + + Ret + +EndP SetBackSampleSegment + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc MFS8Bit ; EDX:AX = 32.16 bytes offset. + ; to mix + + + Push AX + Push EDX + + Mov EDI, CURRENTPOSITION + Call SetSampleSegment + + Xor CX, CX ; EDI = CurrentPosition & (2^14-1) + + Mov EBX, 0FFFEh + + Sub CX, CURRENTPOSITIONERROR + SBB EBX, EDI + ; EBX:CX = 64k-(CurrentPosition & (2^14-1)) + ; EDX:AX = blocksize + Cmp EDX, EBX + JBE MFS8Bit1 + + Mov EDX, EBX + Mov AX, CX + +MFS8Bit1: + ; Now to calculate bytes to mix... + ShL EAX, 16 + SHRD EAX, EDX, 16 + ShR EDX, 16 ; EDX:EAX = (16)32.16 offset + + Mov EBX, STEPVALUE + Cmp EDX, EBX + JAE MFS8Bit2 + + Div EBX + Add EDX, 0FFFFFFFFh + AdC EAX, 0 ; EAX = no of bytes to mix + JZ MFS8Bit2 + + Push EAX + + Xor ECX, ECX + Mov DELTAOFFSET, [SI+4] ; Stepvalue + Mov DELTAERROR, [SI+2] ; Stepvalue + Mov CX, CURRENTPOSITIONERROR + + Push DS + Push SI + + Mov SI, MixBufferOffset + Mov DS, MixSegment + Call [MixFunction] + + Pop SI + Pop DS + Pop ECX + Jmp MFS8Bit3 + +MFS8Bit2: +; Xor ECX, ECX + Pop EDX + Pop AX + + Ret + +MFS8Bit3: + ; Update pointers... + Mov EAX, STEPVALUE + Mul ECX + + Sub MixBlockSize, CX + ShL CX, RESOLUTIONSHIFT + Add MixBufferOffset, CX + + ; EDX:EAX = offset mixed (32.16) + ShLD EDX, EAX, 16 + Mov BX, AX + Mov ECX, EDX ; ECX:BX = offset mixed + + Add CURRENTPOSITIONERROR, BX + AdC CURRENTPOSITION, ECX + + Pop EDX + Pop AX + + Sub AX, BX + SBB EDX, ECX + + JG MFS8Bit + + Ret + +EndP MFS8Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc MFS16Bit + + Push AX + Push EDX + + Mov EDI, CURRENTPOSITION + Add EDI, EDI + Call SetSampleSegment + + ShR EDI, 1 ; EDI = number of samples. + + Xor CX, CX + + Mov EBX, 7FFEh + + Sub CX, CURRENTPOSITIONERROR + SBB EBX, EDI + + Cmp EDX, EBX + JBE MFS16Bit1 + + Mov EDX, EBX + Mov AX, CX + +MFS16Bit1: + ; Now to calculate bytes to mix... + ShL EAX, 16 + SHRD EAX, EDX, 16 + ShR EDX, 16 ; EDX:EAX = (16)32.16 offset + + Mov EBX, STEPVALUE + Cmp EDX, EBX + JAE MFS16Bit2 + + Div EBX + Add EDX, 0FFFFFFFFh + AdC EAX, 0 ; EAX = no of bytes to mix + JZ MFS16Bit2 + + Push EAX + + Xor ECX, ECX + Mov DELTAOFFSET, [SI+4] ; Stepvalue + Mov DELTAERROR, [SI+2] ; Stepvalue + Mov CX, CURRENTPOSITIONERROR + + Push DS + Push SI + + Mov SI, MixBufferOffset + Mov DS, MixSegment + Call [MixFunction] + + Pop SI + Pop DS + Pop ECX + Jmp MFS16Bit3 + +MFS16Bit2: +; Xor ECX, ECX + Pop EDX + Pop AX + Ret + +MFS16Bit3: + ; Update pointers... + Mov EAX, STEPVALUE + Mul ECX + + Sub MixBlockSize, CX + ShL CX, RESOLUTIONSHIFT + Add MixBufferOffset, CX + + ; EDX:EAX = offset mixed (32.16) + ShLD EDX, EAX, 16 + Mov BX, AX + Mov ECX, EDX ; ECX:BX = offset mixed + + Add CURRENTPOSITIONERROR, BX + AdC CURRENTPOSITION, ECX + + Pop EDX + Pop AX + + Sub AX, BX + SBB EDX, ECX + + JG MFS16Bit + + Ret + +EndP MFS16Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc MBS8Bit + + Push AX + Push EDX ; EDX:AX = 32.16 blocksize + + Mov EDI, CURRENTPOSITION + Mov EBX, EDI + Add EBX, 2 + ShR EBX, 14 ; BX = frame + + Sub BX, 3 + JNC MBS8Bit4 + + Xor BX, BX + +MBS8Bit4: + Mov ECX, EBX + ShL ECX, 14 + Sub EDI, ECX + + Call SetBackSampleSegment + + Mov ECX, CURRENTPOSITION + Mov BX, CURRENTPOSITIONERROR + And ECX, 16383 + Add ECX, 0BFFEh + Cmp ECX, EDX + JG MBS8Bit1 + JL MBS8Bit5 + Cmp BX, AX + JG MBS8Bit1 + +MBS8Bit5: + Mov EDX, ECX + Mov AX, BX + +MBS8Bit1: + + ; Now to calculate bytes to mix... + ShL EAX, 16 + SHRD EAX, EDX, 16 + ShR EDX, 16 ; EDX:EAX = (16)32.16 offset + + Mov EBX, STEPVALUE + Cmp EDX, EBX + JAE MBS8Bit2 + + Div EBX + Add EDX, 0FFFFFFFFh + AdC EAX, 0 ; EAX = no of bytes to mix + JZ MBS8Bit2 + + Push EAX + + Xor ECX, ECX + Mov EBP, [SI+2] ; Stepvalue + Neg EBP + ShLD EDX, EBP, 16 + + Mov CX, CURRENTPOSITIONERROR + + Push DS + Push SI + + Mov SI, MixBufferOffset + Mov DS, MixSegment + Call [MixFunction] + + Pop SI + Pop DS + Pop ECX + Jmp MBS8Bit3 + +MBS8Bit2: +; Xor ECX, ECX + Pop EDX + Pop AX + Ret + +MBS8Bit3: + ; Update pointers... + Mov EAX, STEPVALUE + Mul ECX + + Sub MixBlockSize, CX + ShL CX, RESOLUTIONSHIFT + Add MixBufferOffset, CX + + ; EDX:EAX = offset mixed (32.16) + ShLD EDX, EAX, 16 + Mov BX, AX + Mov ECX, EDX ; ECX:BX = offset mixed + + Sub CURRENTPOSITIONERROR, BX + SBB CURRENTPOSITION, ECX + + Pop EDX + Pop AX + + Sub AX, BX + SBB EDX, ECX + + JG MBS8Bit + + Ret + +EndP MBS8Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc MBS16Bit + + Push AX + Push EDX ; EDX:AX = 32.16 blocksize + + Mov EDI, CURRENTPOSITION + Mov EBX, EDI + Add EBX, 4 + ShR EBX, 13 ; BX = frame + + Sub BX, 3 + JNC MBS16Bit4 + + Xor BX, BX + +MBS16Bit4: + Mov ECX, EBX + ShL ECX, 13 + Sub EDI, ECX + + Call SetBackSampleSegment + + Mov ECX, CURRENTPOSITION + Mov BX, CURRENTPOSITIONERROR + And ECX, 8191 + Add ECX, 05FFEh + Cmp ECX, EDX + JG MBS16Bit1 + JL MBS16Bit5 + Cmp BX, AX + JG MBS16Bit1 + +MBS16Bit5: + Mov EDX, ECX + Mov AX, BX + +MBS16Bit1: + + ; Now to calculate bytes to mix... + ShL EAX, 16 + SHRD EAX, EDX, 16 + ShR EDX, 16 ; EDX:EAX = (16)32.16 offset + + Mov EBX, STEPVALUE + Cmp EDX, EBX + JAE MBS16Bit2 + + Div EBX + Add EDX, 0FFFFFFFFh + AdC EAX, 0 ; EAX = no of bytes to mix + JZ MBS16Bit2 + + Push EAX + + Xor ECX, ECX + Mov EBP, [SI+2] ; Stepvalue + Neg EBP + ShLD EDX, EBP, 16 + + Mov CX, CURRENTPOSITIONERROR + + Push DS + Push SI + + Mov SI, MixBufferOffset + Mov DS, MixSegment + Call [MixFunction] + + Pop SI + Pop DS + Pop ECX + Jmp MBS16Bit3 + +MBS16Bit2: +; Xor ECX, ECX + Pop EDX + Pop AX + Ret + +MBS16Bit3: + ; Update pointers... + Mov EAX, STEPVALUE + Mul ECX + + Sub MixBlockSize, CX + ShL CX, RESOLUTIONSHIFT + Add MixBufferOffset, CX + + ; EDX:EAX = offset mixed (32.16) + ShLD EDX, EAX, 16 + Mov BX, AX + Mov ECX, EDX ; ECX:BX = offset mixed + + Sub CURRENTPOSITIONERROR, BX + SBB CURRENTPOSITION, ECX + + Pop EDX + Pop AX + + Sub AX, BX + SBB EDX, ECX + + JG MBS16Bit + + Ret + +EndP MBS16Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReportError + + Ret + +EndP ReportError + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + diff --git a/SoundDrivers/MLPT1.BAT b/SoundDrivers/MLPT1.BAT new file mode 100755 index 0000000..f7b9a13 --- /dev/null +++ b/SoundDrivers/MLPT1.BAT @@ -0,0 +1,4 @@ +tasm /m /ut310 lpt1drv +tlink /3 lpt1drv +execom lpt1drv itlpt1.drv +copy itlpt1.drv .. diff --git a/SoundDrivers/MLPT2.BAT b/SoundDrivers/MLPT2.BAT new file mode 100755 index 0000000..9f3b39b --- /dev/null +++ b/SoundDrivers/MLPT2.BAT @@ -0,0 +1,4 @@ +tasm /m /ut310 lpt2drv +tlink /3 lpt2drv +execom lpt2drv itlpt2.drv +copy itlpt2.drv .. diff --git a/SoundDrivers/MMID.BAT b/SoundDrivers/MMID.BAT new file mode 100755 index 0000000..9d1760f --- /dev/null +++ b/SoundDrivers/MMID.BAT @@ -0,0 +1,4 @@ +tasm /m /ut310 middrv +tlink /3 middrv +execom middrv itmid.drv +copy itmid.drv .. diff --git a/SoundDrivers/MMIDI.BAT b/SoundDrivers/MMIDI.BAT new file mode 100755 index 0000000..d9f2c56 --- /dev/null +++ b/SoundDrivers/MMIDI.BAT @@ -0,0 +1,4 @@ +tasm /m /ut310 mididrv +tlink /3 mididrv +execom mididrv itmpu401.drv +copy itmpu401.drv .. diff --git a/SoundDrivers/MMX.INC b/SoundDrivers/MMX.INC new file mode 100755 index 0000000..680eed8 --- /dev/null +++ b/SoundDrivers/MMX.INC @@ -0,0 +1,306 @@ + +; Stuff from Intel's MMX Macro set. + +; This stuff has been written for real mode use - change the EQU below to EAX +; for protected mode use. + +opc_rdTSC = 031h +opc_Rdpmc = 033H +opc_Emms = 077H +opc_Movd_ld = 06EH +opc_Movd_st = 07EH +opc_Movq_ld = 06FH +opc_Movq_st = 07FH +opc_Packssdw = 06BH +opc_Packsswb = 063H +opc_Packuswb = 067H +opc_Paddb = 0FCH +opc_Paddd = 0FEH +opc_Paddsb = 0ECH +opc_Paddsw = 0EDH +opc_Paddusb = 0DCH +opc_Paddusw = 0DDH +opc_Paddw = 0FDH +opc_Pand = 0DBH +opc_Pandn = 0DFH +opc_Pcmpeqb = 074H +opc_Pcmpeqd = 076H +opc_Pcmpeqw = 075H +opc_Pcmpgtb = 064H +opc_Pcmpgtd = 066H +opc_Pcmpgtw = 065H +opc_Pmaddwd = 0F5H +opc_Pmulhw = 0E5H +opc_Pmullw = 0D5H +opc_Por = 0EBH +opc_PSHimd = 072H +opc_PSHimq = 073H +opc_PSHimw = 071H +opc_Pslld = 0F2H +opc_Psllq = 0F3H +opc_Psllw = 0F1H +opc_Psrad = 0E2H +opc_Psraw = 0E1H +opc_Psrld = 0D2H +opc_Psrlq = 0D3H +opc_Psrlw = 0D1H +opc_Psubb = 0F8H +opc_Psubd = 0FAH +opc_Psubsb = 0E8H +opc_Psubsw = 0E9H +opc_Psubusb = 0D8H +opc_Psubusw = 0D9H +opc_Psubw = 0F9H +opc_Punpcklbw = 060H +opc_Punpckldq = 062H +opc_Punpcklwd = 061H +opc_Punpckhbw = 068H +opc_Punpckhdq = 06AH +opc_Punpckhwd = 069H +opc_Pxor = 0EFH + +.486P + +MM0 EQU AX +MM1 EQU CX +MM2 EQU DX +MM3 EQU BX +MM4 EQU SP +MM5 EQU BP +MM6 EQU SI +MM7 EQU DI + +MMXMacro Macro Dst, Src, Opcode + Local X, Y + X: CmpXChg Src, Dst + Y: Org X+1 + DB Opcode + Org Y + EndM + +MMXIMacro Macro Dst, Src, Opcode + Local X, Y + X: BT Dst, Src + Y: Org X+1 + DB Opcode + Org Y + EndM + +MMXSRMacro Macro Dst, Src, Opcode + Local X, Y + X: CmpXChg Dst, MM2 + DB Src + Y: Org X+1 + DB Opcode + Org Y + EndM + +MMXSLMacro Macro Dst, Src, Opcode + Local X, Y + X: BTR Dst, Src + Y: Org X+1 + DB Opcode + Org Y + EndM + + +EMMS Macro + DB 0Fh, opc_Emms + EndM + + +MovQ Macro Dst, Src + MMXMacro Dst, Src, opc_MovQ_LD + EndM + +MovQM Macro Dst, Src + MMXMacro Src, Dst, opc_MovQ_ST + EndM + +MovD Macro Dst, Src + MMXMacro Dst, Src, opc_MovD_LD + EndM + +MovDM Macro Dst, Src + MMXMacro Src, Dst, opc_MovD_ST + EndM + +MovDR Macro Dst, Src + MMXMacro Src, Dst, opc_MovD_ST + EndM + + +PackSSDW Macro Dst, Src + MMXMacro Dst, Src, opc_PackSSDW + EndM + +PackSSWB Macro Dst, Src + MMXMacro Dst, Src, opc_PackSSWB + EndM + + +PAnd Macro Dst, Src + MMXMacro Dst, Src, opc_PAnd + EndM + +PAndN Macro Dst, Src + MMXMacro Dst, Src, opc_PAndN + EndM + + +PAddD Macro Dst, Src + MMXMacro Dst, Src, opc_PAddD + EndM + +PAddSW Macro Dst, Src + MMXMacro Dst, Src, opc_PAddSW + EndM + +PAddW Macro Dst, Src + MMXMacro Dst, Src, opc_PAddW + EndM + + +PMAddWD Macro Dst, Src + MMXMacro Dst, Src, opc_PMAddWD + EndM + +PMulHW Macro Dst, Src + MMXMacro Dst, Src, opc_PMulHW + EndM + +PMulLW Macro Dst, Src + MMXMacro Dst, Src, opc_PMulLW + EndM + + +POr Macro Dst, Src + MMXMacro Dst, Src, opc_POr + EndM + + +PSLLD Macro Dst, Src + MMXMacro Dst, Src, opc_PSLLD + EndM + +PSLLDI Macro Dst, Src + MMXSLMacro Dst, Src, opc_PSHImd + EndM + +PSLLQ Macro Dst, Src + MMXMacro Dst, Src, opc_PSLLQ + EndM + +PSLLQI Macro Dst, Src + MMXSLMacro Dst, Src, opc_PSHImq + EndM + + +PSRAD Macro Dst, Src + MMXMacro Dst, Src, opc_PSRAD + EndM + +PSRADI Macro Dst, Src + MMXIMacro Dst, Src, opc_PSHImd + EndM + +PSRLD Macro Dst, Src + MMXMacro Dst, Src, opc_PSRLD + EndM + +PSRLDI Macro Dst, Src + MMXSRMacro Dst, Src, opc_PSHImd + EndM + +PSRLQ Macro Dst, Src + MMXMacro Dst, Src, opc_PSRLQ + EndM + +PSRLQI Macro Dst, Src + MMXSRMacro Dst, Src, opc_PSHImq + EndM + +PSRAW Macro Dst, Src + MMXMacro Dst, Src, opc_PSRAW + EndM + +PSRAWI Macro Dst, Src + MMXIMacro Dst, Src, opc_PSHImw + EndM + +PSRLW Macro Dst, Src + MMXMacro Dst, Src, opc_PSRLW + EndM + +PSRLWI Macro Dst, Src + MMXSRMacro Dst, Src, opc_PSHImw + EndM + + +PSubB Macro Dst, Src + MMXMacro Dst, Src, opc_PSubB + EndM + +PSubSB Macro Dst, Src + MMXMacro Dst, Src, opc_PSubSB + EndM + +PSubUSB Macro Dst, Src + MMXMacro Dst, Src, opc_PSubUSB + EndM + +PSubD Macro Dst, Src + MMXMacro Dst, Src, opc_PSubD + EndM + +PSubW Macro Dst, Src + MMXMacro Dst, Src, opc_PSubW + EndM + +PSubSW Macro Dst, Src + MMXMacro Dst, Src, opc_PSubSW + EndM + +PSubUSW Macro Dst, Src + MMXMacro Dst, Src, opc_PSubUSW + EndM + + +PUnpckHBW Macro Dst, Src + MMXMacro Dst, Src, opc_PUnpckHBW + EndM + +PUnpckHDQ Macro Dst, Src + MMXMacro Dst, Src, opc_PUnpckHDQ + EndM + +PUnpckHWD Macro Dst, Src + MMXMacro Dst, Src, opc_PUnpckHWD + EndM + +PUnpckLBW Macro Dst, Src + MMXMacro Dst, Src, opc_PUnpckLBW + EndM + +PUnpckLDQ Macro Dst, Src + MMXMacro Dst, Src, opc_PUnpckLDQ + EndM + +PUnpckLWD Macro Dst, Src + MMXMacro Dst, Src, opc_PUnpckLWD + EndM + + +PXor Macro Dst, Src + MMXMacro Dst, Src, opc_PXor + EndM + + +RdPMC Macro + DB 0Fh, opc_Rdpmc + EndM + +RdTSC Macro + DB 0Fh, opc_RdTSC + EndM + diff --git a/SoundDrivers/MMXMSAM.INC b/SoundDrivers/MMXMSAM.INC new file mode 100755 index 0000000..72233ee --- /dev/null +++ b/SoundDrivers/MMXMSAM.INC @@ -0,0 +1,388 @@ +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Align 4 +include q.inc +FilterParameters DB 64 Dup (07Fh), 64 Dup (0) +Const2048 DD 16384.0 +FreqMultiplier DD 3A9F7867h ; = 1/(2*PI*110.0*2^0.25) +FreqParameterMultiplier DD 0B92AAAAAh ; = -1/(24*256) + +NUMBEROFFILTERBANDS = 4 + +IF OUTPUTFILTERENABLED +LastFilter DD NUMBEROFFILTERBANDS*2 Dup (0) ; 4 stereo values +FilterCoefficients DD NUMBEROFFILTERBANDS*2 Dup (0) +FilterVolumes DD NUMBEROFFILTERBANDS Dup (0) +ENDIF + +FilterFreqValue DW 0 +NewControlWord DW 7Fh + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc MixSamples ; Given DS:SI = info tables, CX = numchannels + Assume DS:Nothing + + ; 1. Clean buffer + ; + update variables + ; 2. Update parameters + ; 3. Mix func + ; 4. Return + + Push CX + + Mov CX, BytesToMix + Mov ES, CS:MixSegment + Mov DI, DMABUFFERLENGTH*2+80 + Xor EAX, EAX + Mov DX, CX + Add CX, CX + + Mov CS:MixTransferOffset, DI + + Cmp CS:Stereo, 0 + JE CS:MixSamples1 + + Mov DX, CX + +MixSamples1: + Rep StosD + Mov CS:MixTransferRemaining, DX + + Pop CX + +MixSamples2: + Test Byte Ptr [SI], 1 + JZ MixSamplesEnd2 + + Cmp Byte Ptr [SI+36h], 100 + JE MixSamplesEnd2 + + Push CX + Mov CX, [SI] + + Test CH, 2 + JZ MixSamplesNoStop + + And Byte Ptr [SI], Not 1 + + Cmp MixMode, 2 + JB MixSamplesEnd + + Mov DWord Ptr [SI+0Ch], 0 + Jmp MixModeCommon + +MixSamplesNoStop: + Test CL, 20h ; New freq? + JZ MixSamples5 + + Mov AX, [SI+10h] + Mov DX, [SI+12h] + Mov BX, MixSpeed + Cmp DX, BX + JAE MixSamplesHandleError + + Div BX + ShL EAX, 16 + Xor AX, AX + Div BX + Mov STEPVALUE, EAX + +MixSamples4: + Test CH, 1 + JZ MixSamples5 + + Xor EAX, EAX + Mov [SI+3Ch], AX ; For filter. + Mov [SI+6Eh], AX + + Mov DWord Ptr [SI+1Ch], EAX ; Current Volume = 0 + ; for volume sliding. + Mov [SI+06h], DX + Mov [SI+5Eh], AX + Mov [SI+7Eh], AX + +MixSamples5: + Test CX, 8540h ; New volume or panning? + JZ MixSamplesMix + + Mov AX, 4*60 + + Test CH, 8 ; Muted? + JZ MixMMXNoMute + + Xor EDX, EDX + Mov [SI+06h], DX + Mov [SI+0Ch], EDX + Mov [SI+5Eh], DX + Mov [SI+1Ch], EDX + Mov [SI+6Eh], DX + Mov [SI+3Ch], DX + Mov [SI+7Eh], DX + + Xor BX, BX + Mov BL, [SI+3Ah] + + Test BL, BL + JS MixModeCommon1 + + Mov DL, [CS:FilterParameters+BX] + Mov BL, [CS:FilterParameters+BX+64] + + Mov [SI+5Bh], DL + Mov [SI+3Fh], BL + + Jmp MixModeCommon1 + +MixMMXNoMute: + Xor BX, BX + Mov BL, [SI+3Ah] + + Test BL, BL ; Disowned? Then use channel filters. + JNS MixGetChannelFilters + + Mov BL, [SI+3Fh] + Jmp MixChannelFilters + +MixGetChannelFilters: + ; Filter = [FilterParameters+BX] + ; Q = [FilterParameters+BX+64] + + Mov AL, [CS:FilterParameters+BX] ; AX = Filter + Mov BL, [CS:FilterParameters+BX+64] ; BX = Q + +; If the values are different, then force recalculate volume. (and hence mixmode) + + Cmp [SI+5Bh], AL + JE MixChannelFiltersSame + Cmp [SI+3Fh], BL + JE MixChannelFiltersSame + + Mov DWord Ptr [SI+0Ch], 0 + +MixChannelFiltersSame: + Mov [SI+5Bh], AL + Mov [SI+3Fh], BL + +MixChannelFilters: + Cmp MixMode, 3 + JNE MixMMXNoFilters + + Mov AL, [SI+3Eh] + Mul Byte Ptr [SI+5Bh] + + Mov CS:FilterFreqValue, AX + + Cmp AX, 127*255 + JNE MixChannelFiltersOK + Test BL, BL + JZ MixMMXNoFilters + +MixChannelFiltersOK: + ShL BX, 2 + + FNInit + FLdCW [CS:NewControlWord] + + FILD [CS:FilterFreqValue] ; 0->127*256 + FMul [CS:FreqParameterMultiplier] ; -i/(24*256) + FLd ST + FRndInt + FSub ST(1), ST + FXCh + F2XM1 + FLd1 + FAdd + FScale ; = 2^(i/24*256) + FMul [CS:FreqMultiplier] ; = r + FLd ST ; r, r + FMul ST(1), ST ; r, r^2 + + FLd [CS:QualityFactorTable+BX] ; 2d, r, r^2 + FMul ST(1), ST ; 2d, 2dr, r^2 + FAdd + + FLd1 ; 1, d+1, e + FXCh ; d+1, 1, e + FSubR ST(1), ST + FAdd ST, ST(2) ; 1+d+e, d, e + FDivR Const2048 ; 1/(1+d+e), d, e + FISt Word Ptr [SI+5Eh] ; + FLd ST(2) ; e, 1/(1+d+e), d, e + FAdd ST, ST + FAddP ST(2), ST ; 1/(1+d+e), d+2e, e + FMul ST(2), ST ; 1/(1+d+e), d+2e, e/(1+d+e) + FMul + FIStP Word Ptr [SI+6Eh] + FChs + FIStP Word Ptr [SI+7Eh] + FStP ST + Mov DWord Ptr [SI+0Ch], 0 + +MixMMXNoFilters: + Mov EBX, [SI+0Ch] + + Cmp Stereo, 0 + JNE MixMMXStereo + +MixMMXMono: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 9 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + + Jmp MixModeVolumeCheck + +MixMMXStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE MixMMXSurround + + Mul Byte Ptr MixVolume ; 0->128 + Mul Word Ptr [SI+4Ah] ; 0->32768 + ShRD AX, DX, 15 ; Maxvol = 8192 + Mov [SI+0Eh], AX ; Store into right volume + + Mov AL, 64 ; Do left volume + Sub AL, [SI+37h] ; AL = 64-FinalPan + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 15 + Mov [SI+0Ch], AX + + Jmp MixModeVolumeCheck + +MixMMXSurround: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 10 + Mov [SI+0Ch], AX + Neg AX + Mov [SI+0Eh], AX + +MixModeVolumeCheck: + Test CH, 3+4 + JNZ MixModeCommon + + Cmp EBX, [SI+0Ch] ; Same as last volume? + JE MixSamplesMix + +MixModeCommon: ; Requires AX = 30 etc. depending + ; On mixing mode type. + ; This will add 180 for 16-bit, + ; And sort out loop types. + Mov AX, MixModeOffset + + Cmp DWord Ptr [SI+0Ch], 0 + JNE MixModeActualMix + + Cmp MixMode, 2 + JB MixMMXGeneralNoRamp + + Cmp DWord Ptr [SI+1Ch], 0 + JNE MixModeActualMix + +MixMMXGeneralNoRamp: + Mov AX, 4*60 + Jmp MixModeCommon1 + +MixModeActualMix: + Cmp MixMode, 3 + JNE MixModeFilter + + Cmp Word Ptr [SI+6Eh], 0 + JNE MixModeFilter + Cmp Word Ptr [SI+7Eh], 0 + JNE MixModeFilter + + Sub AX, 60 + +MixModeFilter: + Test Byte Ptr [SI+18h], 2 ; 16 bit? + JZ MixModeCommon1 + + Add AX, 30 + +MixModeCommon1: + Cmp Byte Ptr [SI+0Ah], 8 + JB MixModeCommon3 ; No loop + JE MixModeCommon2 ; Forwards loop + + Add AX, 10 + +MixModeCommon2: + Add AX, 10 + +MixModeCommon3: + Add AX, Offset MixFunctionTables + Mov [SI+8], AX ; Offset... + +MixSamplesMix: + Mov BX, [SI+8] ; BX = offset into + Mov EAX, [CS:BX+2] + Mov DWord Ptr PreMixFunction, EAX + Mov EAX, [CS:BX+6] + Mov DWord Ptr MixFunctionSeparateBackwards, EAX + + Mov AX, BytesToMix + Mov MixBlockSize, AX + Mov MixBufferOffset, DMABUFFERLENGTH*2+80 + + Mov EAX, CURRENTPOSITION + Mov OLDPOSITION, EAX + + Push Word Ptr [SI+8] + Call Word Ptr [CS:BX] + Pop BX + + And Word Ptr [SI], 0111100010001101b + + Cmp BX, Offset MixFunctionTables+60*2 + JB MixSamplesEnd + Cmp BX, Offset MixFunctionTables+60*4 + JAE MixSamplesEnd + + MovDR AX, MM6 + Mov [SI+0Ch], EAX + Mov [SI+1Ch], EAX + + Cmp BX, Offset MixfunctionTables+60*3 + JB MixSamplesEnd + + Mov ES, CS:MixSegment + Mov DX, [ES:10h] + Mov BX, [ES:14h] + Mov [SI+3Ch], DX + Mov [SI+6h], BX + Jmp MixSamplesEnd + +MixSamplesHandleError: + Mov Word Ptr [SI], 200h + + Test Byte Ptr [SI+3Ah], 80h + JNZ MixSamplesEnd + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Turn off channel + +MixSamplesEnd: + Pop CX + +MixSamplesEnd2: + Add SI, 128 + Dec CX + JNZ MixSamples2 + +IF OUTPUTFILTERENABLED + include equalize.inc +ENDIF + Ret + +EndP MixSamples + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + diff --git a/SoundDrivers/MMXTRANS.INC b/SoundDrivers/MMXTRANS.INC new file mode 100755 index 0000000..25dd6a0 --- /dev/null +++ b/SoundDrivers/MMXTRANS.INC @@ -0,0 +1,116 @@ + +; To be embedded within the IRQ handler. + + Push DX + + Cmp CS:Stereo, 0 + JNE TransferStereoBufferMMX + +TransferMonoBufferMMX: ; DX = number of 32 bit numbers -> 16 bit. + + Push DX + ShR DX, 3 + JZ TransferMonoBufferMMX2 + +TransferMonoBufferMMX1: + MovD MM0, [SI] + MovD MM4, [SI+8] + MovD MM1, [SI+10h] + PUnpckLDQ MM0, MM4 + MovD MM5, [SI+18h] + PSRADI MM0, 13 + MovD MM2, [SI+20h] + PUnpckLDQ MM1, MM5 + MovD MM6, [SI+28h] + PSRADI MM1, 13 + MovD MM3, [SI+30h] + PUnpckLDQ MM2, MM6 + MovD MM7, [SI+38h] + PSRADI MM2, 13 + + PUnpckLDQ MM3, MM7 + PackSSDW MM0, MM1 + + PSRADI MM3, 13 + + MovQM [DI], MM0 + PackSSDW MM2, MM3 + + MovQM [DI+8], MM2 + + Add SI, 40h + Add DI, 10h + + Dec DX + JNZ TransferMonoBufferMMX1 + +TransferMonoBufferMMX2: + Pop CX + Mov DX, CX + + And CX, 7 + JZ TransferMonoBufferMMX4 + +TransferMonoBufferMMX3: + MovD MM0, [SI] + PSRADI MM0, 13 + PackSSDW MM0, MM1 + MovDR AX, MM0 + StosW + Add SI, 8 + + Loop TransferMonoBufferMMX3 + +TransferMonoBufferMMX4: + Jmp MMXMixTransferEnd + +TransferStereoBufferMMX: ; DX is always an even number for stereo + Push DX + + ShR DX, 3 + JZ TransferStereoBufferMMX2 + +TransferStereoBufferMMX1: ; DX = number of 32 bit numbers -> 16 bit + MovQ MM0, [SI] + MovQ MM1, [SI+10h] + PSRADI MM0, 12 + MovQ MM2, [SI+8] + PSRADI MM1, 12 + MovQ MM3, [SI+18h] + PSRADI MM2, 12 + PackSSDW MM0, MM2 + PSRADI MM3, 12 + MovQM [DI], MM0 + PackSSDW MM1, MM3 + MovQM [DI+8], MM1 ; 8 values done. + + Add SI, 20h + Add DI, 10h + + Dec DX + JNZ TransferStereoBufferMMX1 + +TransferStereoBufferMMX2: + Pop CX + Mov DX, CX + + And CX, 7 + ShR CX, 1 ; Always an even number! + JZ TransferStereoBufferMMX4 + +TransferStereoBufferMMX3: + MovQ MM0, [SI] + PSRADI MM0, 12 + PackSSDW MM0, MM1 ; Dummy register + MovDM [DI], MM0 + Add SI, 8 + Add DI, 4 + + Dec CX + JNZ TransferStereoBufferMMX3 + +TransferStereoBufferMMX4: + +MMXMixTransferEnd: + Pop DX + diff --git a/SoundDrivers/MNOMIX.INC b/SoundDrivers/MNOMIX.INC new file mode 100755 index 0000000..5843cd7 --- /dev/null +++ b/SoundDrivers/MNOMIX.INC @@ -0,0 +1,9 @@ + + DW Offset UpdateNoLoop, 0, 0, 0, 0 ; Update only + DW Offset UpdateForwardsLoop, 0, 0, 0, 0 + DW Offset UpdatePingPongLoop, 0, 0, 0, 0 + + DW Offset UpdateNoLoop, 0, 0, 0, 0 ; Update only + DW Offset UpdateForwardsLoop, 0, 0, 0, 0 + DW Offset UpdatePingPongLoop, 0, 0, 0, 0 + diff --git a/SoundDrivers/MONO12B.INC b/SoundDrivers/MONO12B.INC new file mode 100755 index 0000000..59998e9 --- /dev/null +++ b/SoundDrivers/MONO12B.INC @@ -0,0 +1,17 @@ + + DW Offset UpdateNoLoop, 0, 0, 0, 0 ; Update only + DW Offset UpdateForwardsLoop, 0, 0, 0, 0 + DW Offset UpdatePingPongLoop, 0, 0, 0, 0 + ; Central + DW Offset MixNoLoop, PreMix12Central8Bit, MFS8Bit, MBS8Bit, Mix12Central8Bit + DW Offset MixForwardsLoop, PreMix12Central8Bit, MFS8Bit, MBS8Bit, Mix12Central8Bit + DW Offset MixPingPongLoop, PreMix12Central8Bit, MFS8Bit, MBS8Bit, Mix12Central8Bit + + ; 16 bit tables + DW Offset UpdateNoLoop, 0, 0, 0, 0 ; Update only + DW Offset UpdateForwardsLoop, 0, 0, 0, 0 + DW Offset UpdatePingPongLoop, 0, 0, 0, 0 + ; Central + DW Offset MixNoLoop, PreMix12Central16Bit, MFS16Bit, MBS16Bit, Mix12Central16Bit + DW Offset MixForwardsLoop, PreMix12Central16Bit, MFS16Bit, MBS16Bit, Mix12Central16Bit + DW Offset MixPingPongLoop, PreMix12Central16Bit, MFS16Bit, MBS16Bit, Mix12Central16Bit diff --git a/SoundDrivers/MONO12B.MIX b/SoundDrivers/MONO12B.MIX new file mode 100755 index 0000000..9de6da1 --- /dev/null +++ b/SoundDrivers/MONO12B.MIX @@ -0,0 +1,188 @@ + +ERROR EQU CX +DELTAERROR EQU BP +DELTAOFFSET EQU DX + + ; Different mixing routines required: + ; Left } shared + ; Right } + ; Central + ; Surround + ; Panned ; Each requires 8 bit and 16 bit + ; Single output - for Mono, pure left/pure right + +M12Mix8Central Macro Index + +M12Mix8Central&Index&: + Mov BL, [ES:DI] ;; 2 + Add ERROR, DELTAERROR ;; 1 + Mov AX, [EBX+EBX] ;; 2 + AdC DI, DELTAOFFSET ;; 1 + Sub [SI+(Index-15)*2], AX + +EndM + +M12Mix16Central Macro Index + +M12Mix16Central&Index&: + Mov BL, [ES:EDI+EDI+1] + Add ERROR, DELTAERROR + Mov AX, [EBX+EBX] + AdC DI, DELTAOFFSET + Sub [SI+(Index-15)*2], AX + +EndM + +;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Mix12Central8BitOffsetTable Label Word + + IndexCounter = 15 + + M12Mix8CentralOffset Macro Index + DW Offset M12Mix8Central&Index& + EndM + + REPT 16 + M12Mix8CentralOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix12Central8Bit + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Push [CS:Mix12Central8BitOffsetTable+BX] + +M12Central8BitVolume EQU $+3 + Mov EBX, 0 ; Set BH = volume + + RetN + + M12Mix8Central 0 + M12Mix8Central 1 + M12Mix8Central 2 + M12Mix8Central 3 + M12Mix8Central 4 + M12Mix8Central 5 + M12Mix8Central 6 + M12Mix8Central 7 + M12Mix8Central 8 + M12Mix8Central 9 + M12Mix8Central 10 + M12Mix8Central 11 + M12Mix8Central 12 + M12Mix8Central 13 + M12Mix8Central 14 + M12Mix8Central 15 + + Add SI, 32 + Dec LoopCounter + JNZ M12Mix8Central0 + + Ret + +EndP Mix12Central8Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix12Central8Bit + + Mov AL, [SI+0Eh] + Mov Byte Ptr [CS:M12Central8BitVolume], AL + + Ret + +EndP PreMix12Central8Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Mix12Central16BitOffsetTable Label Word + + IndexCounter = 15 + + M12Mix16CentralOffset Macro Index + DW Offset M12Mix16Central&Index& + EndM + + REPT 16 + M12Mix16CentralOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix12Central16Bit + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Push [CS:Mix12Central16BitOffsetTable+BX] + +M12Central16BitVolume EQU $+3 + Mov EBX, 0 ; Set BH = volume + + + RetN + + M12Mix16Central 0 + M12Mix16Central 1 + M12Mix16Central 2 + M12Mix16Central 3 + M12Mix16Central 4 + M12Mix16Central 5 + M12Mix16Central 6 + M12Mix16Central 7 + M12Mix16Central 8 + M12Mix16Central 9 + M12Mix16Central 10 + M12Mix16Central 11 + M12Mix16Central 12 + M12Mix16Central 13 + M12Mix16Central 14 + M12Mix16Central 15 + + Add SI, 32 + Dec LoopCounter + JNZ M12Mix16Central0 + + Ret + +EndP Mix12Central16Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix12Central16Bit + + Mov AL, [SI+0Eh] + Mov Byte Ptr [CS:M12Central16BitVolume], AL + + Ret + +EndP PreMix12Central16Bit + + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + diff --git a/SoundDrivers/MONO12BI.INC b/SoundDrivers/MONO12BI.INC new file mode 100755 index 0000000..4ad266f --- /dev/null +++ b/SoundDrivers/MONO12BI.INC @@ -0,0 +1,17 @@ + + DW Offset UpdateNoLoop, 0, 0, 0, 0 ; Update only + DW Offset UpdateForwardsLoop, 0, 0, 0, 0 + DW Offset UpdatePingPongLoop, 0, 0, 0, 0 + ; Central + DW Offset MixNoLoop, PreMix12Central8BitI, MFS8Bit, MBS8Bit, Mix12Central8BitI + DW Offset MixForwardsLoop, PreMix12Central8BitI, MFS8Bit, MBS8Bit, Mix12Central8BitI + DW Offset MixPingPongLoop, PreMix12Central8BitI, MFS8Bit, MBS8Bit, Mix12Central8BitI + + ; 16 bit tables + DW Offset UpdateNoLoop, 0, 0, 0, 0 ; Update only + DW Offset UpdateForwardsLoop, 0, 0, 0, 0 + DW Offset UpdatePingPongLoop, 0, 0, 0, 0 + ; Central + DW Offset MixNoLoop, PreMix12Central16BitI, MFS16Bit, MBS16Bit, Mix12Central16BitI + DW Offset MixForwardsLoop, PreMix12Central16BitI, MFS16Bit, MBS16Bit, Mix12Central16BitI + DW Offset MixPingPongLoop, PreMix12Central16BitI, MFS16Bit, MBS16Bit, Mix12Central16BitI diff --git a/SoundDrivers/MONO12BI.MIX b/SoundDrivers/MONO12BI.MIX new file mode 100755 index 0000000..eb01312 --- /dev/null +++ b/SoundDrivers/MONO12BI.MIX @@ -0,0 +1,242 @@ + +ERROR EQU CX +DELTAERROR EQU BP +DELTAOFFSET EQU DX +HIGHERROR EQU CH + + ; Different mixing routines required: + ; Left } shared + ; Right } + ; Central + ; Surround + ; Panned ; Each requires 8 bit and 16 bit + ; Single output - for Mono, pure left/pure right + + ; Interpolation = [DI+1]*Error + [DI]*(1-Error) + ; = [DI+1]*Error + [DI] - [DI]*Error + ; = Error*([DI+1]-[DI]) + [DI] + + +M12Mix8ICentral Macro Index + +M12Mix8ICentral&Index&: + Mov AX, [ES:DI] + Mov BL, AL + SAR AL, 1 + SAR AH, 1 + Sub AH, AL + Mov AL, CH + ShR AL, 1 + IMul AH + SHL AX, 2 + Add BL, AH + +M12Mix8ICentralVolume&Index& EQU $+1 + Mov BH, 12h + + Add ERROR, DELTAERROR ;; 1 + Mov AX, [EBX+EBX] + AdC DI, DELTAOFFSET ;; 1 + Sub [SI+(Index-15)*2], AX + +EndM + +M12Mix16ICentral Macro Index + +M12Mix16ICentral&Index&: + Mov BX, [ES:EDI+EDI] + Mov AH, [ES:EDI+EDI+3] + Mov BL, BH + SAR AH, 1 + SAR BH, 1 + Sub AH, BH + Mov AL, CH + ShR AL, 1 + IMul AH + SHL AX, 2 + Add BL, AH + +M12Mix16ICentralVolume&Index& EQU $+1 + Mov BH, 12h + + Add ERROR, DELTAERROR ;; 1 + Mov AX, [EBX+EBX] + AdC DI, DELTAOFFSET ;; 1 + Sub [SI+(Index-15)*2], AX + +EndM + +;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Mix12Central8BitIOffsetTable Label Word + + IndexCounter = 15 + + M12Mix8ICentralOffset Macro Index + DW Offset M12Mix8ICentral&Index& + EndM + + REPT 16 + M12Mix8ICentralOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix12Central8BitI + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Push [CS:Mix12Central8BitIOffsetTable+BX] + + Xor EBX, EBX + + RetN + + M12Mix8ICentral 0 + M12Mix8ICentral 1 + M12Mix8ICentral 2 + M12Mix8ICentral 3 + M12Mix8ICentral 4 + M12Mix8ICentral 5 + M12Mix8ICentral 6 + M12Mix8ICentral 7 + M12Mix8ICentral 8 + M12Mix8ICentral 9 + M12Mix8ICentral 10 + M12Mix8ICentral 11 + M12Mix8ICentral 12 + M12Mix8ICentral 13 + M12Mix8ICentral 14 + M12Mix8ICentral 15 + + Add SI, 32 + Dec LoopCounter + JNZ M12Mix8ICentral0 + + Ret + +EndP Mix12Central8BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix12Central8BitI + + Mov AL, [SI+0Eh] + + IndexCounter = 0 + + PreMix12Central8BitIMacro Macro Index + Mov Byte Ptr [CS:M12Mix8ICentralVolume&Index&], AL + EndM + + REPT 16 + PreMix12Central8BitIMacro %IndexCounter + IndexCounter = IndexCounter+1 + EndM + + Ret + +EndP PreMix12Central8BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Mix12Central16BitIOffsetTable Label Word + + IndexCounter = 15 + + M12Mix16ICentralOffset Macro Index + DW Offset M12Mix16ICentral&Index& + EndM + + REPT 16 + M12Mix16ICentralOffset %IndexCounter + IndexCounter = IndexCounter-1 + EndM + +Proc Mix12Central16BitI + + Dec AX + Mov BX, AX + And AX, 0Fh + ShR BX, 4 + Add AX, AX + Inc BX + Mov LoopCounter, BX + Mov BX, AX + + ShL AX, RESOLUTIONSHIFT-1 + + Add SI, AX + + Push [CS:Mix12Central16BitIOffsetTable+BX] + + Xor EBX, EBX + + + RetN + + M12Mix16ICentral 0 + M12Mix16ICentral 1 + M12Mix16ICentral 2 + M12Mix16ICentral 3 + M12Mix16ICentral 4 + M12Mix16ICentral 5 + M12Mix16ICentral 6 + M12Mix16ICentral 7 + M12Mix16ICentral 8 + M12Mix16ICentral 9 + M12Mix16ICentral 10 + M12Mix16ICentral 11 + M12Mix16ICentral 12 + M12Mix16ICentral 13 + M12Mix16ICentral 14 + M12Mix16ICentral 15 + + Add SI, 32 + Dec LoopCounter + JNZ M12Mix16ICentral0 + + Ret + +EndP Mix12Central16BitI + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreMix12Central16BitI + + Mov AL, [SI+0Eh] + + IndexCounter = 0 + + PreMix12Central16BitIMacro Macro Index + Mov Byte Ptr [CS:M12Mix16ICentralVolume&Index&], AL + EndM + + REPT 16 + PreMix12Central16BitIMacro %IndexCounter + IndexCounter = IndexCounter+1 + EndM + + Ret + + + Ret + +EndP PreMix12Central16BitI + + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + diff --git a/SoundDrivers/MPAS.BAT b/SoundDrivers/MPAS.BAT new file mode 100755 index 0000000..042d7cc --- /dev/null +++ b/SoundDrivers/MPAS.BAT @@ -0,0 +1,4 @@ +tasm /m /ut310 pasdrv +tlink /3 pasdrv +execom pasdrv itpas.drv +copy itpas.drv .. diff --git a/SoundDrivers/MPAS16.BAT b/SoundDrivers/MPAS16.BAT new file mode 100755 index 0000000..5ca635d --- /dev/null +++ b/SoundDrivers/MPAS16.BAT @@ -0,0 +1,4 @@ +tasm /m /ut310 pas16drv +tlink /3 pas16drv +execom pas16drv itpas16.drv +copy itpas16.drv .. diff --git a/SoundDrivers/MPC.BAT b/SoundDrivers/MPC.BAT new file mode 100755 index 0000000..20b3a4a --- /dev/null +++ b/SoundDrivers/MPC.BAT @@ -0,0 +1,4 @@ +tasm /m /ut310 pcspkdrv +tlink /3 pcspkdrv +execom pcspkdrv itpcspkr.drv +copy itpcspkr.drv .. diff --git a/SoundDrivers/MSAM.BAT b/SoundDrivers/MSAM.BAT new file mode 100755 index 0000000..cf35dec --- /dev/null +++ b/SoundDrivers/MSAM.BAT @@ -0,0 +1,5 @@ +tasm /m /ut310 sam9407 +tlink /3 sam9407 +execom sam9407 it9407.drv +copy it9407.drv .. + diff --git a/SoundDrivers/MSB.BAT b/SoundDrivers/MSB.BAT new file mode 100755 index 0000000..85d9c8b --- /dev/null +++ b/SoundDrivers/MSB.BAT @@ -0,0 +1,4 @@ +tasm /m /ut310 sbdrv +tlink /3 sbdrv +execom sbdrv itsb.drv +copy itsb.drv .. diff --git a/SoundDrivers/MSB16.BAT b/SoundDrivers/MSB16.BAT new file mode 100755 index 0000000..f99b353 --- /dev/null +++ b/SoundDrivers/MSB16.BAT @@ -0,0 +1,5 @@ +tasm /m /ut310 sb16drv +tlink /3 sb16drv +execom sb16drv itsb16.drv +copy itsb16.drv .. + diff --git a/SoundDrivers/MSB16A.BAT b/SoundDrivers/MSB16A.BAT new file mode 100755 index 0000000..e503e5d --- /dev/null +++ b/SoundDrivers/MSB16A.BAT @@ -0,0 +1,5 @@ +tasm32 /m /ut310 sb16k6 +tlink /3 sb16k6 +execom sb16k6 itsb16.3dn +copy itsb16.3dn .. + diff --git a/SoundDrivers/MSB16B.BAT b/SoundDrivers/MSB16B.BAT new file mode 100755 index 0000000..fc14dda --- /dev/null +++ b/SoundDrivers/MSB16B.BAT @@ -0,0 +1,4 @@ +tasm /m /uT310 sb16b +tlink /3 sb16b +execom sb16b itsb16b.drv +copy itsb16b.drv .. diff --git a/SoundDrivers/MSB16C.BAT b/SoundDrivers/MSB16C.BAT new file mode 100755 index 0000000..9285cb4 --- /dev/null +++ b/SoundDrivers/MSB16C.BAT @@ -0,0 +1,4 @@ +tasm /m /uT310 sb16c +tlink /3 sb16c +execom sb16c itsb16c.drv +copy itsb16c.drv .. diff --git a/SoundDrivers/MSB16D.BAT b/SoundDrivers/MSB16D.BAT new file mode 100755 index 0000000..4f3ad2e --- /dev/null +++ b/SoundDrivers/MSB16D.BAT @@ -0,0 +1,4 @@ +tasm /m /uT310 sb16d +tlink /3 sb16d +execom sb16d itsb16d.drv +copy itsb16d.drv .. diff --git a/SoundDrivers/MSB16M.BAT b/SoundDrivers/MSB16M.BAT new file mode 100755 index 0000000..e2923f3 --- /dev/null +++ b/SoundDrivers/MSB16M.BAT @@ -0,0 +1,5 @@ +tasm32 /m /ut310 sb16mmx +tlink /3 sb16mmx +execom sb16mmx itsb16.mmx +copy itsb16.mmx .. + diff --git a/SoundDrivers/MSB16MB.BAT b/SoundDrivers/MSB16MB.BAT new file mode 100755 index 0000000..0839be9 --- /dev/null +++ b/SoundDrivers/MSB16MB.BAT @@ -0,0 +1,5 @@ +tasm32 /m /ut310 sb16mmxb +tlink /3 sb16mmxb +execom sb16mmxb itsb16b.mmx +copy itsb16b.mmx .. + diff --git a/SoundDrivers/MSB2.BAT b/SoundDrivers/MSB2.BAT new file mode 100755 index 0000000..65f8c0f --- /dev/null +++ b/SoundDrivers/MSB2.BAT @@ -0,0 +1,4 @@ +tasm /m /ut310 sb2drv +tlink /3 sb2drv +execom sb2drv itsb2.drv +copy itsb2.drv .. diff --git a/SoundDrivers/MSBPRO.BAT b/SoundDrivers/MSBPRO.BAT new file mode 100755 index 0000000..88bd0d6 --- /dev/null +++ b/SoundDrivers/MSBPRO.BAT @@ -0,0 +1,4 @@ +tasm /m /ut310 sbprodrv +tlink /3 sbprodrv +execom sbprodrv itsbpro.drv +copy itsbpro.drv .. diff --git a/SoundDrivers/MST97.BAT b/SoundDrivers/MST97.BAT new file mode 100755 index 0000000..b2fd60a --- /dev/null +++ b/SoundDrivers/MST97.BAT @@ -0,0 +1,4 @@ +tasm /m /ut310 st97 +tlink /3 st97 +execom st97 itst97.drv +copy itst97.drv .. diff --git a/SoundDrivers/MSTC.BAT b/SoundDrivers/MSTC.BAT new file mode 100755 index 0000000..fe8212e --- /dev/null +++ b/SoundDrivers/MSTC.BAT @@ -0,0 +1,5 @@ +tasm /m /ut310 st97code +tlink /3 st97code +execom st97code itstcode.drv +copy itstcode.drv .. + diff --git a/SoundDrivers/MSTCM.BAT b/SoundDrivers/MSTCM.BAT new file mode 100755 index 0000000..62f7644 --- /dev/null +++ b/SoundDrivers/MSTCM.BAT @@ -0,0 +1,4 @@ +tasm32 /m /la /ut310 st97cmmx +tlink /3 st97cmmx +execom st97cmmx itstcode.mmx +copy itstcode.mmx .. diff --git a/SoundDrivers/MSTP.BAT b/SoundDrivers/MSTP.BAT new file mode 100755 index 0000000..23bbdca --- /dev/null +++ b/SoundDrivers/MSTP.BAT @@ -0,0 +1,5 @@ +tasm /m /ut310 st97pnp +tlink /3 st97pnp +execom st97pnp itstpnp.drv +copy itstpnp.drv .. + diff --git a/SoundDrivers/MT.BAT b/SoundDrivers/MT.BAT new file mode 100755 index 0000000..e4c4fd6 --- /dev/null +++ b/SoundDrivers/MT.BAT @@ -0,0 +1,5 @@ +tasm /m /ut310 test +tlink /3 test +execom test ittest.drv +copy ittest.drv .. + diff --git a/SoundDrivers/MV.BAT b/SoundDrivers/MV.BAT new file mode 100755 index 0000000..38807c4 --- /dev/null +++ b/SoundDrivers/MV.BAT @@ -0,0 +1,5 @@ +tasm32 /m /ut310 /la vsnd +tlink /3 vsnd +execom vsnd itvsound.drv +copy itvsound.drv .. + diff --git a/SoundDrivers/MVIVO.BAT b/SoundDrivers/MVIVO.BAT new file mode 100755 index 0000000..9394270 --- /dev/null +++ b/SoundDrivers/MVIVO.BAT @@ -0,0 +1,5 @@ +tasm /m /ut310 envivo +tlink /3 envivo +execom envivo itvivo.drv +copy itvivo.drv .. + diff --git a/SoundDrivers/MVM.BAT b/SoundDrivers/MVM.BAT new file mode 100755 index 0000000..dd16587 --- /dev/null +++ b/SoundDrivers/MVM.BAT @@ -0,0 +1,5 @@ +tasm32 /m /ut310 /la vsndmmx +tlink /3 /m vsndmmx +execom vsndmmx itvsound.mmx +copy itvsound.mmx .. + diff --git a/SoundDrivers/MWAV.BAT b/SoundDrivers/MWAV.BAT new file mode 100755 index 0000000..d0210dc --- /dev/null +++ b/SoundDrivers/MWAV.BAT @@ -0,0 +1,4 @@ +tasm /m /ut310 wavdrv +tlink /3 wavdrv +execom wavdrv itwav.drv +call mmid diff --git a/SoundDrivers/MWSS.BAT b/SoundDrivers/MWSS.BAT new file mode 100755 index 0000000..11d267d --- /dev/null +++ b/SoundDrivers/MWSS.BAT @@ -0,0 +1,5 @@ +tasm /m /ut310 wssdrv +tlink /3 wssdrv +execom wssdrv itwss.drv +copy itwss.drv .. + diff --git a/SoundDrivers/MWSS2.BAT b/SoundDrivers/MWSS2.BAT new file mode 100755 index 0000000..fef0fa1 --- /dev/null +++ b/SoundDrivers/MWSS2.BAT @@ -0,0 +1,5 @@ +tasm /m /ut310 wssdrv2 +tlink /3 wssdrv2 +execom wssdrv2 itwss2.drv +copy itwss2.drv .. + diff --git a/SoundDrivers/NODEBUG.INC b/SoundDrivers/NODEBUG.INC new file mode 100755 index 0000000..f7ad96f --- /dev/null +++ b/SoundDrivers/NODEBUG.INC @@ -0,0 +1,7 @@ +; +; Dummy trace commands +; + + +Trace Macro LogMessage + EndM diff --git a/SoundDrivers/NOISE.ASM b/SoundDrivers/NOISE.ASM new file mode 100755 index 0000000..ed80341 --- /dev/null +++ b/SoundDrivers/NOISE.ASM @@ -0,0 +1,2091 @@ +; +; Windows Sound System Driver +; + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;********************************** + +STEREOENABLED EQU 1 +DMABUFFERLENGTH EQU 8192 +MIXRESOLUTION EQU 32 ; 32 bit mixing for +MIXTABLESIZE EQU 2*256*65 + +DMASize DW 2048 + +WSSMsg DB "Using Noise Source Codec", 13 + DB "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, DMA ", 0FDh, "D", 0 + +WSSNoMemoryMsg DB "Using Noise Source Codec", 13 + DB "Error: Insufficient memory", 0 + +ReinitMsg DB "Noise Source reinitialised", 0 + +ConfigErrorMsg DB "Error saving configuration to ITNOISE.DRV", 0 +ConfigOKMsg DB "Configuration saved to ITNOISE.DRV", 0 + +DriverName DB "ITNOISE.DRV", 0 + +Forced DB 0 +Stereo DB 0 +MixVolume DW 0 + +BytesToMix DW 1000 +WSSMixConst DB 0 + +MixSegment DW 0 +DMASegment DW 0 + +MixTransferOffset DW 0 +MixTransferRemaining DW 0 + +CONFIGURATIONOFFSET EQU $+128 +CONFIGSIZE EQU 6 +MixMode DW 0 +MixModeOffset DW 0 +Filter DW 0 + +IMR DW 0 +OldWSSIRQHandler DD 0 + +FilterValue DD 0 +FilterValue2 DD 0 + +MixSpeedTable DW 5513, 41h + DW 6615, 4Fh + DW 8000, 40h + DW 9600, 4Eh + DW 11025, 43h + DW 16000, 42h + DW 18900, 45h + DW 22050, 47h + DW 27429, 44h + DW 32000, 46h + DW 33075, 4Dh + DW 37800, 49h + DW 44100, 4Bh + DW 48000, 4Ch + DW 54860, 48h + DW 64000, 4Ah + +IRQData Label Word + DW 20h, 1111111111111110b ; IRQ 0 + DW 24h, 1111111111111101b ; IRQ 1 + DW 28h, 1111110111111011b ; IRQ 2 + DW 2Ch, 1111111111110111b ; IRQ 3 + DW 30h, 1111111111101111b ; IRQ 4 + DW 34h, 1111111111011111b ; IRQ 5 + DW 38h, 1111111110111111b ; IRQ 6 + DW 3Ch, 1111111101111111b ; IRQ 7 + DW 1C0h, 1111111011111011b ; IRQ 8 + DW 1C4h, 1111110111111011b ; IRQ 9 + DW 1C8h, 1111101111111011b ; IRQ 10 + DW 1CCh, 1111011111111011b ; IRQ 11 + DW 1D0h, 1110111111111011b ; IRQ 12 + DW 1D4h, 1101111111111011b ; IRQ 13 + DW 1D8h, 1011111111111011b ; IRQ 14 + DW 1DCh, 0111111111111011b ; IRQ 15 + +;********************************** +; WSS Registers +;********************************** + +CODEC_INDEX_LIC = 00 +CODEC_INDEX_RIC = 01h +CODEC_INDEX_LX1C = 02h +CODEC_INDEX_RX1C = 03h +CODEC_INDEX_LX2C = 04h +CODEC_INDEX_RX2C = 05h +CODEC_INDEX_LDC = 06h +CODEC_INDEX_RDC = 07h +CODEC_INDEX_CDF = 08h +CODEC_INDEX_INTF = 09h +CODEC_INDEX_PIN = 0Ah +CODEC_INDEX_TEST = 0Bh +CODEC_INDEX_MISC = 0Ch +CODEC_INDEX_DIGMIX = 0Dh +CODEC_INDEX_UPR_COUNT = 0Eh +CODEC_INDEX_LWR_COUNT = 0Fh + +CODEC_MCE = 40h + +LDC_LDM = 80h +LDC_LDA = 3Fh + +RDC_RDM = 80h +RDC_RDA = 3Fh + +CDF_STEREO = 10h + +INTF_PEN = 01h +INTF_CEN = 02h +INTF_SDC = 04h +INTF_ACAL = 08h +INTF_PPIO = 40h +INTF_CPIO = 80h + +PIN_IEN = 2 + +TEST_ORL = 03h +TEST_ORR = 0Ch +TEST_DRS = 10h +TEST_ACI = 20h +TEST_PUR = 40h +TEST_COR = 80h + +;********************************** + +WSS16ScreenList Label + DW 16 + DW Near Ptr IdleFunctionList + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr WSSHeaderLine + + DW Near Ptr DriverText + + DW Near Ptr MixModeText + DW Near Ptr MixModeButton1 ; 6 + DW Near Ptr MixModeButton2 ; + DW Near Ptr MixModeButton3 ; 8 + DW Near Ptr MixModeButton4 ; 9 + + DW Near Ptr FilterText + DW Near Ptr FilterButton1 ; 11 + DW Near Ptr FilterButton2 + DW Near Ptr FilterButton3 + + DW Near Ptr VolumeText + DW Near Ptr VolumeBox1 + + DW Near Ptr MasterVolumeLeft ; 16 + DW Near Ptr MasterVolumeRight ; 17 + + DW 0 + +WSSHeaderLine DW 10 + DB "Noise Source Codec Driver", 0 + +EmptyObject DW 1 + DB 0, 0 + DB 0 + DB 0 + +DriverText DW 1 + DB 29, 48 + DB 21h + DB "Noise Source Codec Driver 1.0 for Impulse Tracker", 0 + +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +IdleFunctionList DD 0 + DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +VolumeText DW 1 + DB 2, 14 + DB 20h + DB "Master Volume Left", 13 + DB "Master Volume Right" + DB 0 + +VolumeBox1 DW 0 + DB 21, 13, 31, 16 + DB 25 + +MasterVolumeLeft DW 9 + DB 22, 14 + DW 0, 63 + DW 9, 0 + DW 0FFFFh, 17, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +MasterVolumeRight DW 9 + DB 22, 15 + DW 0, 63 + DW 9, 1 + DW 16, 6, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +MixModeText DW 1 + DB 2, 18 + DB 20h + DB "Mixing Mode, Playback Frequency: ", 0FDh, "DHz", 0 +MixSpeed DW 48000 + +MixModeButton1 DW 2 + DW 17, 7, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment1 DW 0 + DW 0 + DW Offset SetMixMode +DriverSegment2 DW 0 + DB 3, 20, 32, 22, 8 + DB 0 + DB " 16 Bit, Non-Interpolated", 0 + +MixModeButton2 DW 2 + DW 6, 8, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment3 DW 0 + DW 2 + DW Offset SetMixMode +DriverSegment4 DW 0 + DB 3, 23, 32, 25, 8 + DB 0 + DB " 16 Bit, Interpolated", 0 + +MixModeButton3 DW 2 + DW 7, 9, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment5 DW 0 + DW 4 + DW Offset SetMixMode +DriverSegment6 DW 0 + DB 3, 26, 32, 28, 8 + DB 0 + DB " 32 Bit, Non-Interpolated", 0 + +MixModeButton4 DW 2 + DW 8, 11, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment7 DW 0 + DW 6 + DW Offset SetMixMode +DriverSegment8 DW 0 + DB 3, 29, 32, 31, 8 + DB 0 + DB " 32 Bit, Interpolated", 0 + +FilterText DW 1 + DB 2, 33 + DB 20h + DB "Filter mode", 0 + +FilterButton1 DW 2 + DW 9, 12, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment9 DW 0 + DW 0 + DW Offset SetFilter +DriverSegment10 DW 0 + DB 3, 35, 29, 37, 8 + DB 0 + DB " No Filter", 0 + +FilterButton2 DW 2 + DW 11, 13, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment11 DW 0 + DW 1 + DW Offset SetFilter +DriverSegment12 DW 0 + DB 3, 38, 29, 40, 8 + DB 0 + DB " 50% Filter", 0 + +FilterButton3 DW 2 + DW 12, 0FFFFh, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment13 DW 0 + DW 2 + DW Offset SetFilter +DriverSegment14 DW 0 + DB 3, 41, 29, 43, 8 + DB 0 + DB " 75% Filter", 0 + +VolumeTable DB 2 Dup (0) + +; ÄÄ MixingRoutines ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixBufferPos DW 0 + +include dma.inc +include mix.inc +include m12bit.mix +include m12biti.mix +include m32bit.mix +include m32biti.mix + +MixFunctionTables Label + +include m12bit.inc ; contains the tables +include m12biti.inc +include m32bit.inc +include m32biti.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +RelocationTable Label Word + DW Offset DriverSegment1, Offset DriverSegment2 + DW Offset DriverSegment3, Offset DriverSegment4 + DW Offset DriverSegment5, Offset DriverSegment6 + DW Offset DriverSegment7, Offset DriverSegment8 + DW Offset DriverSegment9, Offset DriverSegment10 + DW Offset DriverSegment11, Offset DriverSegment12 + DW Offset DriverSegment13, Offset DriverSegment14 + DW 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixMode Far + + Push CS + Pop ES + Mov DI, Offset MixMode + + Ret + +EndP GetMixMode + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetFilter Far + + Push CS + Pop ES + Mov DI, Offset Filter + + Ret + +EndP GetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetFilter Far + + Mov AX, [SI+22] + Mov CS:FilterValue, 0 + Mov CS:Filter, AX + ClI + Jmp SetMixModeChain + +EndP SetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WaitCoDec + + Push CX + + Mov CX, 0F000h + +WaitCoDec1: + In AL, DX + Test AL, AL + JNS WaitCoDec2 + Loop WaitCoDec1 + + StC + +WaitCoDec2: + Pop CX + Ret + +EndP WaitCoDec + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WaitAutoCalibration + + Push CX + Mov CX, 0F000h + +WaitAutoCalibration1: + Mov AL, CODEC_INDEX_TEST + Out DX, AL + Inc DX + In AL, DX + Dec DX + Test AL, TEST_ACI + JNZ WaitAutoCalibration2 + Loop WaitAutoCalibration1 + + StC + +WaitAutoCalibration2: + Pop CX + Ret + +EndP WaitAutoCalibration + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixMode Far + + Mov AX, [SI+22] + + ClI + + Mov CS:MixMode, AX + + Mov BX, 180 + Mul BX + Mov CS:MixModeOffset, AX + + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS:RecalculateAllVolumes + + StI + +SetMixModeChain: + Call GotoHomeDirectory + + ; Now to save config into driver file. + Push CS + Pop DS + Assume DS:Driver + + Mov AX, 3D02h ; Read write access + Mov DX, Offset DriverName + Mov SI, Offset ConfigErrorMsg + Int 21h + JC SetMixMode1 + + Mov BX, AX + + Mov AX, 4200h + Xor CX, CX + Mov DX, Offset CONFIGURATIONOFFSET + Int 21h + JC SetMixMode2 + + Mov AH, 40h + Mov CX, CONFIGSIZE + Mov DX, Offset MixMode + Int 21h + +SetMixMode2: + PushF + Mov AH, 3Eh + Int 21h + PopF + + JC SetMixMode1 + + Mov SI, Offset ConfigOKMsg + +SetMixMode1: + Mov BX, 40 + Call SetInfoLine + + Mov AX, 1 + Ret + +EndP SetMixMode + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetWSSMixConst ; Work out value.. and nearest + ; mixspeed value. + + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, CmdLineMixSpeed + Mov CX, MixSpeed + Test AX, AX + JZ GetWSSMixConst1 + + Mov CX, 64000 + Cmp AX, CX + JA GetWSSMixConst1 + + Mov CX, 8000 + Cmp AX, CX + JB GetWSSMixConst1 + + Mov CX, AX + +GetWSSMixConst1: ; CX = desired mixspeed + Mov SI, Offset MixSpeedTable + Mov DX, 16 ; 16 different available speeds + + Xor BX, BX + +GetWSSMixConst2: + LodsW + Cmp AX, BX + JB GetWSSMixConst3 + Cmp AX, CX + JA GetWSSMixConst3 + + Mov BX, AX + Mov DH, [SI] + +GetWSSMixConst3: + LodsW ; Add SI, 2 + Dec DL + JNZ GetWSSMixConst2 + + Mov MixSpeed, BX + Mov WSSMixConst, DH + + Pop DS + PopA + Ret + +EndP GetWSSMixConst + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PingWSS ; Check BasePort, DX = BasePort + ; Preserves DX, destroys AX + + Push DX + + Inc DX + Inc DX + + In AL, DX + Xor AL, AL + Out DX, AL + + Dec DX + Dec DX + Call WaitCodec + JC PingWSSFailure + + In AL, DX + Test AL, AL + JS PingWSSFailure + + Mov AL, CODEC_INDEX_MISC + Out DX, AL + Inc DX ; DX = Data port + In AL, DX + Mov AH, AL ; AH = Revision + + Xor AL, AL ; Write 0 revision + Out DX, AL + In AL, DX + And AX, 8F8Fh + Cmp AL, AH + JNE PingWSSFailure + Dec DX ; DX = AD1848 baseport + + Mov AL, CODEC_MCE or CODEC_INDEX_INTF + Out DX, AL + Inc DX + Mov AL, INTF_ACAL or INTF_SDC + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_INTF + Out DX, AL + Inc DX + Mov AL, INTF_ACAL or INTF_SDC + Out DX, AL + Dec DX + + Call WaitAutoCalibration ; Returns carry if error + ; Carry clear if none. + +; JC PingWSSFailure + + Pop DX + Ret + +PingWSSFailure: + Pop DX + + StC + Ret + + +EndP PingWSS + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far + + Push CS + Pop DS + Assume DS:Driver + + Cmp IRQ, 0FFFFh + JE DetectWSSFailure + Cmp DMA, 0FFFFh + JE DetectWSSFailure + + Mov DX, BasePort + Cmp DX, 0FFFFh + JE DetectCardFindBasePort + + Call PingWSS + JNC CheckWSSOK + +DetectWSSFailure: + StC + Ret + +DetectCardFindBasePort: + Mov DX, 31Ch + Call PingWSS + JNC DetectWSSOK + + Mov DX, 32Ch + Call PingWSS + JNC DetectWSSOK + + Mov DX, 33Ch + Call PingWSS + JNC DetectWSSOK + + Mov DX, 34Ch + Call PingWSS + JNC DetectWSSOK + + Mov DX, 35Ch + Call PingWSS + JNC DetectWSSOK + + Mov DX, 36Ch + Call PingWSS + JNC DetectWSSOK + + Mov DX, 530h + Call PingWSS + JNC DetectWSSOK + + Mov DX, 604h + Call PingWSS + JNC DetectWSSOK + + Mov DX, 0F40h + Call PingWSS + JNC DetectWSSOK + + Mov DX, 0E80h + Call PingWSS + JC DetectWSSFailure + +DetectWSSOK: + Mov BasePort, DX + +CheckWSSOK: ; Check for IRQ + Mov AL, CODEC_INDEX_RDC + Out DX, AL + Inc DX + In AL, DX + Mov AH, AL + Dec DX + + Mov AL, CODEC_INDEX_LDC + Out DX, AL + Inc DX + In AL, DX + And AX, 3F3Fh + Neg AL + Neg AH + Add AL, 3Fh + Add AH, 3Fh + Mov [Word Ptr VolumeTable], AX + + Mov EAX, 'Jeff' + ClC + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixModeTable Label Word + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + +Proc MixSamples ; Given DS:SI = info tables, CX = numchannels + + ; 1. Clean buffer + ; + update variables + ; 2. Update parameters + ; 3. Mix func + ; 4. Return + + Push CX + + Mov CX, BytesToMix + Mov ES, MixSegment + Mov DI, MIXTABLESIZE + Xor EAX, EAX + Mov DX, CX + Add CX, CX + + Mov MixTransferOffset, DI ; } Memory write + + Cmp Stereo, 0 + JE MixSamples1 + + Mov DX, CX + +MixSamples1: + Rep StosD ; } Memory write + Mov MixTransferRemaining, DX ; } + + Pop CX + +MixSamples2: + Test Byte Ptr [SI], 1 + JZ MixSamplesEnd2 + Cmp Byte Ptr [SI+36h], 100 + JE MixSamplesEnd2 + + Push CX + Mov CX, [SI] + + Test CH, 2 + JZ MixSamples3 + And Byte Ptr [SI], Not 1 + + Jmp MixSamplesEnd +; Cmp MixMode, 8 ; Is it volume ramping? +; JB MixSamplesEnd + +MixSamples3: + Test CL, 20h ; New freq? + JZ MixSamples5 + + Mov AX, [SI+10h] + Mov DX, [SI+12h] + Mov BX, MixSpeed + Cmp DX, BX + JAE MixSamplesHandleError + + Div BX + ShL EAX, 16 + Xor AX, AX + Div BX + Mov STEPVALUE, EAX + +MixSamples4: + Test CH, 1 + JZ MixSamples5 + + Mov DWord Ptr [SI+1Ch], 0 ; Current Volume = 0 + ; for volume sliding. +MixSamples5: + Test CX, 8440h ; New volume or panning? + JZ MixSamplesMix + + Xor AX, AX + Test CH, 8 ; Muted? + JNZ MixModeCommon + + Mov BX, MixMode + Add BL, Stereo + Add BX, BX + Jmp [CS:MixModeTable+BX] + +Mix0Mode: ; 16-bit mixing, no interpolation +Mix0ModeMono: ; and 16-bit mixing, interpolation + Mov AL, [SI+20h] + ShR AL, 1 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 30 ; Use left only-mixing for mono + Jmp MixModeCommon + +Mix0ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix0ModeSurround + + Mul Byte Ptr [SI+20h] ; Final volume + Add AX, 64 + ShR AX, 7 + Mov [SI+0Ch], AX ; Store into right volume + + Mov AL, 64 + Sub AL, [SI+37h] + Mul Byte Ptr [SI+20h] + Add AX, 64 + ShR AX, 7 + Mov [SI+0Eh], AX ; Left volume + + Mov CH, AL ; CH = left volume + Mov CL, [SI+0Ch] ; CL = right volume + Mov AX, 0 + + Test CX, CX + JZ MixModeCommon + + Mov AL, 30 ; Left only... + Test CL, CL + JZ MixModeCommon + + Mov AL, 60 + Test CH, CH + JZ MixModeCommon + + Mov AL, 90 + Cmp CL, CH + JZ MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix0ModeSurround: + Mov AL, [SI+20h] + ShR AL, 2 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 150 ; Surround + Jmp MixModeCommon + +Mix6ModeMono: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 8 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Test AX, AX + JZ MixModeCommon + Mov AX, 30 + Jmp MixModeCommon + +Mix6ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix6ModeSurround + + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Ch], AX ; Store into right volume + Mov BX, AX + ShL EAX, 16 + + Mov AL, 64 ; Do left volume + Sub AL, [SI+37h] ; AL = 64-FinalPan + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Eh], AX + + Mov ECX, EAX + + ; BX = right volume + ; CX = Left volume + Mov AX, 0 + Test ECX, ECX + JZ MixModeCommon + + Mov AL, 30 + Test BX, BX + JZ MixModeCommon + + Mov AL, 60 + Test CX, CX + JZ MixModeCommon + + Mov AL, 90 + Cmp CX, BX + JE MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix6ModeSurround: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 9 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + JZ MixModeCommon + Mov AX, 150 + Jmp MixModeCommon + +MixModeCommon: ; Requires AX = 30/60/90 etc. depending + ; On mixing mode type. + ; This will add 180 for 16-bit, + ; And sort out loop types. + Mov BL, [SI+0Ah] + Test Byte Ptr [SI+18h], 2 ; 16 bit? + JZ MixModeCommon1 + + Add AX, 180 + +MixModeCommon1: + Cmp BL, 8 + JB MixModeCommon3 ; No loop + JE MixModeCommon2 ; Forwards loop + + Add AX, 10 + +MixModeCommon2: + Add AX, 10 + +MixModeCommon3: + Add AX, Offset MixFunctionTables + Add AX, MixModeOffset + Mov [SI+8], AX ; Offset... + +MixSamplesMix: + Mov BX, [SI+8] ; BX = offset into + Mov EAX, [CS:BX+2] + Mov DWord Ptr PreMixFunction, EAX + Mov EAX, [CS:BX+6] + Mov DWord Ptr MixFunctionSeparateBackwards, EAX + + Mov AX, BytesToMix + Mov MixBlockSize, AX + Mov MixBufferOffset, MIXTABLESIZE + + Mov EAX, CURRENTPOSITION + Mov OLDPOSITION, EAX + + Call Word Ptr [CS:BX] + + And Word Ptr [SI], 0111100010001101b + Jmp MixSamplesEnd + +MixSamplesHandleError: + Mov Word Ptr [SI], 200h + + Test Byte Ptr [SI+3Ah], 80h + JNZ MixSamplesEnd + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Turn off channel + +MixSamplesEnd: + Pop CX + +MixSamplesEnd2: + Add SI, 128 + Dec CX + JNZ MixSamples2 + + Ret + +EndP MixSamples + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WSSIRQHandler + + PushAD + Push DS + Push ES + + ClD + + Mov AX, CS + Mov DS, AX + Assume DS:Driver + + Mov DX, [BasePort] + Add DX, 2 + In AL, DX + Test AL, 1 + JZ WSSAckIRQ2 + + Xor AL, AL + Out DX, AL + +WSSAckIRQ2: + Mov AL, 20h + Cmp IRQ, 8 + JB WSSAckIRQ1 + + Out 0A0h, AL + +WSSAckIRQ1: + Out 20h, AL + + Mov AX, MixBufferPos + Mov BX, AX + Mul DMASize + Cmp AX, DMABUFFERLENGTH + JB WSSIRQHandler2 + + Xor AX, AX + Xor BX, BX + +WSSIRQHandler2: + Inc BX + Mov MixBufferPos, BX + + CLD + + + ; OK... time to get next block + ; Check whether stereo thing is on.. + ; + LES DI, [ActualDMAPtr] + Add DI, AX + + Mov BX, DMASize ; BX = bytes required + ShR BX, 1 + ; BX = samples required + Mov BP, 8 ; Skip for mono + Mov CL, 14 ; Shift for mono + + Cmp Stereo, 0 + JE WSSIRQHandlerMono + + Mov BP, 4 ; Stereo skip value. + Dec CL + +WSSIRQHandlerMono: + Call SaveEMSPageFrame + + Cmp MixTransferRemaining, 0 + JNE WSSIRQHandler4 + Assume DS:Nothing + +WSSIRQHandler3: + Push BX + Push CX + Push BP + Push ES + Push DI + + Call Update + Call MixSamples + + Pop DI + Pop ES + Pop BP + Pop CX + Pop BX + +WSSIRQHandler4: + Mov DS, MixSegment + Mov SI, MixTransferOffset + Mov DX, BX ; DX = samples to transfer + Cmp DX, MixTransferRemaining + JBE WSSIRQHandler5 + + Mov DX, MixTransferRemaining + +WSSIRQHandler5: + Push DX + Cmp CS:Filter, 1 + JB WSSIRQHandler6 + JE WSSIRQHFilter + + Cmp CS:Stereo, 0 + JE WSSIRQ3QFilterMono + +WSSIRQ3QFilterStereo: + Push BX + + Mov EBX, FilterValue + Mov EBP, FilterValue2 + ShR DX, 1 + +WSSIRQ3QFilterStereo1: + Mov EAX, EBX + Mov ECX, EBP + Add EAX, [SI] + Add ECX, [SI+4] + SAR EAX, 1 + SAR ECX, 1 + Add EBX, EAX + Add EBP, ECX + SAR EBX, 1 + SAR EBP, 1 + + Mov EAX, EBX + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSS3QFilterStereoClip1 + Cmp EAX, 7FFFh + JG WSS3QFilterStereoClip2 + +WSSIRQ3QFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSS3QFilterStereoClip3 + Cmp EAX, 7FFFh + JG WSS3QFilterStereoClip4 + +WSSIRQ3QFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ WSSIRQ3QFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp WSSMixTransferEnd + +WSSIRQ3QFilterMono: + Push BX + + Mov EBX, FilterValue + +WSSIRQ3QFilterMono1: + Mov EAX, EBX + Add EAX, [SI] + SAR EAX, 1 + Add EBX, EAX + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL WSS3QFilterMonoClip1 + Cmp EAX, 7FFFh + JG WSS3QFilterMonoClip2 + +WSSIRQ3QFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ WSSIRQ3QFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp WSSMixTransferEnd + +WSSIRQHFilter: + Cmp CS:Stereo, 0 + JE WSSIRQHFilterMono + +WSSIRQHFilterStereo: + Push BX + + Mov EBX, FilterValue + Mov EBP, FilterValue2 + ShR DX, 1 + +WSSIRQHFilterStereo1: + Add EBX, [SI] + Add EBP, [SI+4] + + SAR EBX, 1 + SAR EBP, 1 + + Mov EAX, EBX + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSSHFilterStereoClip1 + Cmp EAX, 7FFFh + JG WSSHFilterStereoClip2 + +WSSIRQHFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSSHFilterStereoClip3 + Cmp EAX, 7FFFh + JG WSSHFilterStereoClip4 + +WSSIRQHFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ WSSIRQHFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp WSSMixTransferEnd + +WSSIRQHFilterMono: + Push BX + + Mov EBX, FilterValue + +WSSIRQHFilterMono1: + Add EBX, [SI] + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL WSSHFilterMonoClip1 + Cmp EAX, 7FFFh + JG WSSHFilterMonoClip2 + +WSSIRQHFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ WSSIRQHFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp WSSMixTransferEnd + +WSSIRQHandler6: + Mov EAX, [SI] + SAR EAX, CL + + Cmp EAX, -8000h + JL WSSIRQHandlerClip1 + Cmp EAX, 7FFFh + JG WSSIRQHandlerClip2 + +WSSIRQHandler7: + StosW ; } Memory write + + Add SI, BP + Dec DX + JNZ WSSIRQHandler6 + +WSSMixTransferEnd: + Pop DX + + Sub MixTransferRemaining, DX ; } Memory write + Sub BX, DX + JNZ WSSIRQHandler3 + + Mov MixTransferOffset, SI ; } Memory write + + Call RestoreEMSPageFrame + + Pop ES + Pop DS + PopAD + IRet + +WSSIRQHandlerClip1: + Mov AX, 8000h + Jmp WSSIRQHandler7 + +WSSIRQHandlerClip2: + Mov AX, 7FFFh + Jmp WSSIRQHandler7 + +WSSHFilterMonoClip1: + Mov AX, 8000h + Jmp WSSIRQHFilterMono2 + +WSSHFilterMonoClip2: + Mov AX, 7FFFh + Jmp WSSIRQHFilterMono2 + +WSSHFilterStereoClip1: + Mov AX, 8000h + Jmp WSSIRQHFilterStereo2 + +WSSHFilterStereoClip2: + Mov AX, 7FFFh + Jmp WSSIRQHFilterStereo2 + +WSSHFilterStereoClip3: + Mov AX, 8000h + Jmp WSSIRQHFilterStereo3 + +WSSHFilterStereoClip4: + Mov AX, 7FFFh + Jmp WSSIRQHFilterStereo3 + +WSS3QFilterMonoClip1: + Mov AX, 8000h + Jmp WSSIRQ3QFilterMono2 + +WSS3QFilterMonoClip2: + Mov AX, 7FFFh + Jmp WSSIRQ3QFilterMono2 + +WSS3QFilterStereoClip1: + Mov AX, 8000h + Jmp WSSIRQ3QFilterStereo2 + +WSS3QFilterStereoClip2: + Mov AX, 7FFFh + Jmp WSSIRQ3QFilterStereo2 + +WSS3QFilterStereoClip3: + Mov AX, 8000h + Jmp WSSIRQ3QFilterStereo3 + +WSS3QFilterStereoClip4: + Mov AX, 7FFFh + Jmp WSSIRQ3QFilterStereo3 + +EndP WSSIRQHandler + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Add DI, Offset IRQData + Mov BX, [CS:DI] + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset WSSIRQHandler + + XChg [ES:BX], EAX + Mov OldWSSIRQHandler, EAX + + Mov AX, IMR + And AX, [DI+2] + + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Pop ES + PopAD + + Ret + +EndP SetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Mov BX, [IRQData+DI] + + Mov EAX, OldWSSIRQHandler + Mov [ES:BX], EAX + + Pop ES + PopAD + + Ret + +EndP ResetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StopWSS + + Mov DX, BasePort + + Mov AL, CODEC_INDEX_INTF + Out DX, AL + Inc DX + In AL, DX + And AL, Not INTF_PEN + Out DX, AL + + Inc DX + In AL, DX + Xor AL, AL + Out DX, AL + + Dec DX + Dec DX + + Mov AL, CODEC_INDEX_PIN + Out DX, AL + Inc DX + Xor AL, AL + Out DX, AL + + Ret + +EndP StopWSS + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StartWSS + + PushA + Push ES + Push DS + + Push CS + Pop DS + Assume DS:Driver + + ; Setup DMA + Mov BX, DMASegment + Xor AX, AX + Mov DX, DMA + Mov DI, DMABUFFERLENGTH + Call SetDMA + + LES DI, ActualDMAPtr + Xor AX, AX + Mov CX, DMABUFFERLENGTH/2 + Rep StosW + + Mov MixBufferPos, 0 + Mov MixTransferRemaining, 0 + + Mov DX, BasePort + Call PingWSS + + Mov AL, CODEC_INDEX_PIN + Out DX, AL + Inc DX + Mov AL, PIN_IEN + Out DX, AL + Dec DX + + Mov AH, WSSMixConst ; Set format/frequency + Cmp Stereo, 0 + JE StartWSS1 + + Or AH, CDF_STEREO + +StartWSS1: + Mov AL, CODEC_MCE or CODEC_INDEX_CDF + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Call WaitCodec + + Mov AL, CODEC_INDEX_CDF + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Call WaitAutoCalibration + + ; Start playback + Mov AL, CODEC_INDEX_LWR_COUNT + Out DX, AL + Inc DX + + Mov AX, DMASize + ShR AX, 1 + + Cmp Stereo, 0 + JE StartWSS2 + + ShR AX, 1 + +StartWSS2: + Dec AX + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_UPR_COUNT + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_INTF + Out DX, AL + Inc DX + In AL, DX + Or AL, INTF_PEN + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_LDC + Out DX, AL + Inc DX + In AL, DX + And AL, Not LDC_LDM + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_RDC + Out DX, AL + Inc DX + In AL, DX + And AL, Not RDC_RDM + Out DX, AL + Dec DX + + Pop DS + Pop ES + PopA + + Ret + +EndP StartWSS + Assume DS:Nothing + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov SI, Offset RelocationTable + +RelocationFix: + LodsW + Test AX, AX + JZ RelocationEnd + Mov BX, AX + Mov [BX], DS + Jmp RelocationFix + + +RelocationEnd: + Call GetEMSPageFrame + Mov EMSPageFrame, AX + + In AL, 0A1h + Mov AH, AL + In AL, 21h + Mov IMR, AX + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + Call GetWSSMixConst + + Mov AX, 2643 + Mul MixSpeed + Add AX, 0FFFFh + AdC DX, 2080 + + Mov BX, (DMABUFFERLENGTH*2)/16 + Add BX, DX + + ; Allocate MixSegment first + Mov AH, 48h + + Int 21h + JNC InitSound1 + +InitSoundNoMemory: + Mov SI, Offset WSSNoMemoryMsg + Ret + +InitSound1: + Mov MixSegment, AX + Add AX, DX + Mov DMASegment, AX + + Call SetIRQ + Call GetTempo + Call SetTempo + + Mov SI, Offset WSSMsg + + Mov AX, BasePort + Mov BX, IRQ + Mov CX, DMA + + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Call ResetIRQ + Call SetIRQ + + Mov SI, Offset ReInitMsg + Mov BX, 40 + Call SetInfoLine + + Mov AL, Stereo + Call SetStereo + + Pop ES + Pop DS + PopA + + Ret + +EndP ReInitSound + Assume DS:Nothing + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, IMR + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Mov AX, MixSegment + Test AX, AX + JZ UnInitSound1 + + Mov ES, AX + Mov AH, 49h ; Release MixSegment + Int 21h + + Call StopWSS + Call ResetIRQ + +UnInitSound1: + Ret + +EndP UnInitSound + Assume DS:Nothing + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + Ret + +EndP Poll + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Push AX + Push BX + Push DX + + Push BX + + Mov AX, MixSpeed + Mov BX, AX + Xor DX, DX + + ShL AX, 1 + RCL DX, 1 ; DX:AX = Mixspeed*2 + + ShR BX, 1 ; BX = Mixspeed/2 + + Add AX, BX + AdC DX, 0 ; DX:AX = Mixspeed*2.5 + + Pop BX ; BX = tempo + Div BX + + Mov BytesToMix, AX + + Pop DX + Pop BX + Pop AX + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + PushA + Push DS + + Mov BX, AX ; BX = MixVolume + Mov CS:MixVolume, BX + + Mov AX, CS:MixSegment + Test AX, AX + JZ SetMixVolume2 + + Mov DS, AX + + Mov CX, MIXTABLESIZE/2 + Mov SI, MIXTABLESIZE-2; Starting point - working backwards + +SetMixVolume1: + Mov AX, CX + + Dec AX ; AH = volume, AL = wave value. + Xor DX, DX + XChg AH, DL ; DL = Volume, AX = wave value + CBW + + IMul DX ; DX:AX = Volume * Wave Value + ; Ranges -8192->8128 + + IMul BX ; DX:AX = Volume * Wave Value * Mixing Volume + ; Ranges -1048576->1040384 + + Add AX, 64 + AdC DX, 0 + + ShRD AX, DX, 7 + Mov [SI], AX + Sub SI, 2 + + Loop SetMixVolume1 + +SetMixVolume2: + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS: RecalculateAllVolumes + + Pop DS + PopA + + Ret + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc RecalculateAllFrequencies + + Call GetChannelTables + +RecalculateAllFrequencies1: + Or Byte Ptr [SI], 32 + + Add SI, 128 + Dec CX + JNZ RecalculateAllFrequencies1 + + Ret + +EndP RecalculateAllFrequencies + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Mov CS:Stereo, AL + Cmp CS:MixSegment, 0 + JE SetStereo1 + + Call StopWSS + Call StartWSS + + Call RecalculateAllFrequencies + +SetStereo1: + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include loadsam.inc + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset WSS16ScreenList + + ClC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far + + Xor AH, AH + Mov AL, [CS:VolumeTable+DI] + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far + + Push DS + Push DX + + Push CS + Pop DS + Assume DS:Driver + + Mov [VolumeTable+DI], AL + + Mov DX, BasePort + + Mov AL, CODEC_INDEX_LDC + Out DX, AL + Inc DX + Mov AX, 3F3Fh + Sub AX, [Word Ptr VolumeTable] + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_RDC + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Pop DX + Pop DS + Ret + +EndP SetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. + +StopAfterPlay DW 0 +DefaultChannels DW 64 + DW 5 Dup (0) + + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/PAS16DRV.ASM b/SoundDrivers/PAS16DRV.ASM new file mode 100755 index 0000000..8a72ec4 --- /dev/null +++ b/SoundDrivers/PAS16DRV.ASM @@ -0,0 +1,1986 @@ + + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;********************************** + +STEREOENABLED EQU 1 +DMABUFFERLENGTH EQU 8192 +MIXRESOLUTION EQU 32 ; 32 bit mixing for the PAS16 +MIXTABLESIZE EQU 2*256*65 +TIMERCONST EQU 11932 + +Debug1 DB 0 +Debug2 DW 0 + +PAS16Msg DB "Pro Audio 16 Spectrum found", 13 + DB "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, DMA ", 0FDh, "D", 0 + +PAS16NoMemoryMsg DB "Pro Audio 16 Spectrum found", 13 + DB "Error: Insufficient memory", 0 + +ReinitMsg DB "Pro Audio 16 Spectrum reinitialised", 0 + +ConfigErrorMsg DB "Error saving configuration to ITPAS16.DRV", 0 +ConfigOKMsg DB "Configuration saved to ITPAS16.DRV", 0 + +DriverName DB "ITPAS16.DRV", 0 + +Forced DB 0 +Stereo DB 0 +MixVolume DW 0 + +BytesToMix DW 1000 +MixSpeed DW 44100 +PASMixConst DW 0 + +MixSegment DW 0 +DMASegment DW 0 + +MixTransferOffset DW 0 +MixTransferRemaining DW 0 + +CONFIGURATIONOFFSET EQU $+128 +CONFIGSIZE EQU 6 +MixMode DW 0 +MixModeOffset DW 0 +Filter DW 0 + +IMR DW 0 +OldIRQHandler DD 0 + +FilterValue DD 0 +FilterValue2 DD 0 +TimerAccumulator DW 0 + +DMALengthTable Label Byte + DB 1, 3, 5, 7, 0C2h, 0C6h, 0CAh, 0CEh + +;********************************** + +PAS16ScreenList Label + DW 6 + DW Near Ptr IdleFunctionList + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr PAS16HeaderLine + + DW Near Ptr DriverText + + DW Near Ptr MixModeText + DW Near Ptr MixModeButton1 ; 6 + DW Near Ptr MixModeButton2 ; + DW Near Ptr MixModeButton3 ; 8 + DW Near Ptr MixModeButton4 ; 9 + + DW Near Ptr FilterText + DW Near Ptr FilterButton1 ; 11 + DW Near Ptr FilterButton2 + DW Near Ptr FilterButton3 + + DW 0 + +PAS16HeaderLine DW 10 + DB "Pro Audio Spectrum 16 Driver", 0 + +EmptyObject DW 1 + DB 0, 0 + DB 0 + DB 0 + +DriverText DW 1 + DB 26, 48 + DB 21h + DB "Pro Audio Spectrum 16 Driver 1.0 for Impulse Tracker", 0 + +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +IdleFunctionList DD 0 + DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +MixModeText DW 1 + DB 2, 13 + DB 20h + DB "Mixing Mode", 0 + +MixModeButton1 DW 2 + DW 0FFFFh, 7, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment1 DW 0 + DW 0 + DW Offset SetMixMode +DriverSegment2 DW 0 + DB 3, 15, 32, 17, 8 + DB 0 + DB " 16 Bit, Non-Interpolated", 0 + +MixModeButton2 DW 2 + DW 6, 8, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment3 DW 0 + DW 2 + DW Offset SetMixMode +DriverSegment4 DW 0 + DB 3, 18, 32, 20, 8 + DB 0 + DB " 16 Bit, Interpolated", 0 + +MixModeButton3 DW 2 + DW 7, 9, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment5 DW 0 + DW 4 + DW Offset SetMixMode +DriverSegment6 DW 0 + DB 3, 21, 32, 23, 8 + DB 0 + DB " 32 Bit, Non-Interpolated", 0 + +MixModeButton4 DW 2 + DW 8, 11, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment7 DW 0 + DW 6 + DW Offset SetMixMode +DriverSegment8 DW 0 + DB 3, 24, 32, 26, 8 + DB 0 + DB " 32 Bit, Interpolated", 0 + +FilterText DW 1 + DB 2, 28 + DB 20h + DB "Filter mode", 0 + +FilterButton1 DW 2 + DW 9, 12, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment9 DW 0 + DW 0 + DW Offset SetFilter +DriverSegment10 DW 0 + DB 3, 30, 29, 32, 8 + DB 0 + DB " No Filter", 0 + +FilterButton2 DW 2 + DW 11, 13, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment11 DW 0 + DW 1 + DW Offset SetFilter +DriverSegment12 DW 0 + DB 3, 33, 29, 35, 8 + DB 0 + DB " 50% Filter", 0 + +FilterButton3 DW 2 + DW 12, 0FFFFh, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment13 DW 0 + DW 2 + DW Offset SetFilter +DriverSegment14 DW 0 + DB 3, 36, 29, 38, 8 + DB 0 + DB " 75% Filter", 0 + +VolumeTable DB 6 Dup (0) + +; ÄÄ MixingRoutines ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixBufferPos DW 0 + +include dma.inc +include mix.inc +include m12bit.mix +include m12biti.mix +include m32bit.mix +include m32biti.mix + +MixFunctionTables Label + +include m12bit.inc ; contains the tables +include m12biti.inc +include m32bit.inc +include m32biti.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +RelocationTable Label Word + DW Offset DriverSegment1, Offset DriverSegment2 + DW Offset DriverSegment3, Offset DriverSegment4 + DW Offset DriverSegment5, Offset DriverSegment6 + DW Offset DriverSegment7, Offset DriverSegment8 + DW Offset DriverSegment9, Offset DriverSegment10 + DW Offset DriverSegment11, Offset DriverSegment12 + DW Offset DriverSegment13, Offset DriverSegment14 + DW 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixMode Far + + Push CS + Pop ES + Mov DI, Offset MixMode + + Ret + +EndP GetMixMode + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetFilter Far + + Push CS + Pop ES + Mov DI, Offset Filter + + Ret + +EndP GetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetFilter Far + + Mov AX, [SI+22] + Mov CS:FilterValue, 0 + Mov CS:Filter, AX + ClI + Jmp SetMixModeChain + +EndP SetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixMode Far + + Mov AX, [SI+22] + + ClI + + Mov CS:MixMode, AX + + Mov BX, 180 + Mul BX + Mov CS:MixModeOffset, AX + + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS:RecalculateAllVolumes + + StI + +SetMixModeChain: + Call GotoHomeDirectory + + ; Now to save config into driver file. + Push CS + Pop DS + Assume DS:Driver + + Mov AX, 3D02h ; Read write access + Mov DX, Offset DriverName + Mov SI, Offset ConfigErrorMsg + Int 21h + JC SetMixMode1 + + Mov BX, AX + + Mov AX, 4200h + Xor CX, CX + Mov DX, Offset CONFIGURATIONOFFSET + Int 21h + JC SetMixMode2 + + Mov AH, 40h + Mov CX, CONFIGSIZE + Mov DX, Offset MixMode + Int 21h + +SetMixMode2: + PushF + Mov AH, 3Eh + Int 21h + PopF + + JC SetMixMode1 + + Mov SI, Offset ConfigOKMsg + +SetMixMode1: + Mov BX, 40 + Call SetInfoLine + + Mov AX, 1 + Ret + +EndP SetMixMode + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixSpeed + Assume DS:Driver + + Push AX + Push CX + Push DX + + Mov DX, 12h + Mov AX, 34DCh + Mov CX, PASMixConst + Cmp CS:Stereo, 0 + JE GetMixSpeed1 + + And CX, Not 1 + +GetMixSpeed1: + Div CX + +GetMixSpeed2: + Mov MixSpeed, AX + + Pop DX + Pop CX + Pop AX + Ret + +EndP GetMixSpeed + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetPASMixConst ; Work out value.. and nearest + ; mixspeed value. + + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, CmdLineMixSpeed + Mov CX, MixSpeed + Test AX, AX + JZ GetPASMixConst1 + + Mov CX, 44100 + Cmp AX, CX + JA GetPASMixConst1 + + Mov CX, 12000 + Cmp AX, CX + JB GetPASMixConst1 + + Mov CX, AX + +GetPASMixConst1: + Mov MixSpeed, CX + + Mov DX, 012h + Mov AX, 34DCh + Div CX + + Mov PASMixConst, AX + Mov BX, AX + + Pop DS + PopA + Ret + +EndP GetPASMixConst + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc TestPAS ; AX = port + + Push AX + + Mov DX, 803h ; Default is 0B8Bh + Xor DX, AX ; DX = Interrupt Control port + In AL, DX + + Cmp AL, 0FFh + JE TestPAS1 + + Mov AH, AL + Xor AL, 11100000b + Out DX, AL + + Jmp $+2 + Jmp $+2 + In AL, DX + + Cmp AL, AH + XChg AH, AL + Out DX, AL + JNE TestPAS1 + + Pop AX + Push AX + + Mov DX, AX ; PAS 16? + Xor DX, 0EF8Bh xor 388h + In AL, DX + Test AL, 8 + JZ TestPAS1 + + Pop AX + + ClC + Ret + +TestPAS1: + Pop AX + StC + Ret + +EndP TestPAS + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, 0BC00h + Mov BX, '??' + Xor CX, CX + Xor DX, DX + Int 2Fh + + Xor BX, CX + Xor BX, DX + Cmp BX, 'M'*256+'V' + JE DetectPAS4 ; MVSound.Sys installed! + +DetectPAS7: + StC + Ret + +DetectPAS4: + Mov AX, BasePort + Cmp AX, 0FFFFh + JE DetectPAS1 + Cmp AX, 388h + JE DetectPAS6 + Cmp AX, 384h + JE DetectPAS6 + Cmp AX, 38Ch + JE DetectPAS6 + Cmp AX, 288h + JNE DetectPAS7 + +DetectPAS6: + Call TestPAS + JNC DetectPAS2 + + Ret + +DetectPAS1: + Mov AX, 388h + Call TestPAS + JNC DetectPAS2 + + Mov AX, 384h + Call TestPAS + JNC DetectPAS2 + + Mov AX, 38Ch + Call TestPAS + JNC DetectPAS2 + + Mov AX, 288h + Call TestPAS + JNC DetectPAS2 + + Ret ; No card! + +DetectPAS2: + Push AX + + Mov AX, 0BC04h + Int 2Fh + + Cmp AX, 'M'*256+'V' + JNE DetectPAS3 + + Pop AX + + Mov BasePort, AX + Mov DMA, BX + Mov IRQ, CX + + Mov AL, [DMALengthTable+BX] + Mov Byte Ptr [DMAPort1], AL + Mov Byte Ptr [DMAPort2], AL + + Mov AX, DMABUFFERLENGTH/2 + Cmp BX, 4 + JB DetectPAS5 + + ShR AX, 1 + +DetectPAS5: + Mov Word Ptr [DMABufferLength1], AX + Mov Word Ptr [DMABufferLength2], AX + + Mov EAX, 'Jeff' + ClC + Ret + +DetectPAS3: + Pop AX + StC + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixModeTable Label Word + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + +Proc MixSamples ; Given DS:SI = info tables, CX = numchannels + + ; 1. Clean buffer + ; + update variables + ; 2. Update parameters + ; 3. Mix func + ; 4. Return + + Push CX + + Mov CX, BytesToMix + Mov ES, MixSegment + Mov DI, MIXTABLESIZE + Xor EAX, EAX + Mov DX, CX + Add CX, CX + + Mov MixTransferOffset, DI ; } Memory write + + Cmp Stereo, 0 + JE MixSamples1 + + Mov DX, CX + +MixSamples1: + Rep StosD ; } Memory write + Mov MixTransferRemaining, DX ; } + + Pop CX + +MixSamples2: + Test Byte Ptr [SI], 1 + JZ MixSamplesEnd2 + Cmp Byte Ptr [SI+36h], 100 + JE MixSamplesEnd2 + + Push CX + Mov CX, [SI] + + Test CH, 2 + JZ MixSamples3 + And Byte Ptr [SI], Not 1 + + Jmp MixSamplesEnd +; Cmp MixMode, 8 ; Is it volume ramping? +; JB MixSamplesEnd + +MixSamples3: + Test CL, 20h ; New freq? + JZ MixSamples5 + + Mov AX, [SI+10h] + Mov DX, [SI+12h] + Mov BX, MixSpeed + Cmp DX, BX + JAE MixSamplesHandleError + + Div BX + ShL EAX, 16 + Xor AX, AX + Div BX + Mov STEPVALUE, EAX + +MixSamples4: + Test CH, 1 + JZ MixSamples5 + + Mov DWord Ptr [SI+1Ch], 0 ; Current Volume = 0 + ; for volume sliding. +MixSamples5: + Test CX, 8440h ; New volume or panning? + JZ MixSamplesMix + + Xor AX, AX + Test CH, 8 ; Muted? + JNZ MixModeCommon + + Mov BX, MixMode + Add BL, Stereo + Add BX, BX + Jmp [CS:MixModeTable+BX] + +Mix0Mode: ; 16-bit mixing, no interpolation +Mix0ModeMono: ; and 16-bit mixing, interpolation + Mov AL, [SI+20h] + ShR AL, 1 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 30 ; Use left only-mixing for mono + Jmp MixModeCommon + +Mix0ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix0ModeSurround + + Mul Byte Ptr [SI+20h] ; Final volume + Add AX, 64 + ShR AX, 7 + Mov [SI+0Ch], AX ; Store into right volume + + Mov AL, 64 + Sub AL, [SI+37h] + Mul Byte Ptr [SI+20h] + Add AX, 64 + ShR AX, 7 + Mov [SI+0Eh], AX ; Left volume + + Mov CH, AL ; CH = left volume + Mov CL, [SI+0Ch] ; CL = right volume + Mov AX, 0 + + Test CX, CX + JZ MixModeCommon + + Mov AL, 30 ; Left only... + Test CL, CL + JZ MixModeCommon + + Mov AL, 60 + Test CH, CH + JZ MixModeCommon + + Mov AL, 90 + Cmp CL, CH + JZ MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix0ModeSurround: + Mov AL, [SI+20h] + ShR AL, 2 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 150 ; Surround + Jmp MixModeCommon + +Mix6ModeMono: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 8 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Test AX, AX + JZ MixModeCommon + Mov AX, 30 + Jmp MixModeCommon + +Mix6ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix6ModeSurround + + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Ch], AX ; Store into right volume + Mov BX, AX + ShL EAX, 16 + + Mov AL, 64 ; Do left volume + Sub AL, [SI+37h] ; AL = 64-FinalPan + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Eh], AX + + Mov ECX, EAX + + ; BX = right volume + ; CX = Left volume + Mov AX, 0 + Test ECX, ECX + JZ MixModeCommon + + Mov AL, 30 + Test BX, BX + JZ MixModeCommon + + Mov AL, 60 + Test CX, CX + JZ MixModeCommon + + Mov AL, 90 + Cmp CX, BX + JE MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix6ModeSurround: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 9 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + JZ MixModeCommon + Mov AX, 150 + Jmp MixModeCommon + +MixModeCommon: ; Requires AX = 30/60/90 etc. depending + ; On mixing mode type. + ; This will add 180 for 16-bit, + ; And sort out loop types. + Mov BL, [SI+0Ah] + Test Byte Ptr [SI+18h], 2 ; 16 bit? + JZ MixModeCommon1 + + Add AX, 180 + +MixModeCommon1: + Cmp BL, 8 + JB MixModeCommon3 ; No loop + JE MixModeCommon2 ; Forwards loop + + Add AX, 10 + +MixModeCommon2: + Add AX, 10 + +MixModeCommon3: + Add AX, Offset MixFunctionTables + Add AX, MixModeOffset + Mov [SI+8], AX ; Offset... + +MixSamplesMix: + Mov BX, [SI+8] ; BX = offset into + Mov EAX, [CS:BX+2] + Mov DWord Ptr PreMixFunction, EAX + Mov EAX, [CS:BX+6] + Mov DWord Ptr MixFunctionSeparateBackwards, EAX + + Mov AX, BytesToMix + Mov MixBlockSize, AX + Mov MixBufferOffset, MIXTABLESIZE + + Mov EAX, CURRENTPOSITION + Mov OLDPOSITION, EAX + + Call Word Ptr [CS:BX] + + And Word Ptr [SI], 0111100010001101b + Jmp MixSamplesEnd + +MixSamplesHandleError: + Mov Word Ptr [SI], 200h + + Test Byte Ptr [SI+3Ah], 80h + JNZ MixSamplesEnd + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Turn off channel + +MixSamplesEnd: + Pop CX + +MixSamplesEnd2: + Add SI, 128 + Dec CX + JNZ MixSamples2 + + Ret + +EndP MixSamples + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PAS16IRQHandler + + Push AX + Push BX + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Add TimerAccumulator, TIMERCONST + JC PAS16IRQHandler11 + + Mov AL, 20h + Out 20h, AL + Jmp PAS16IRQHandler12 + +PAS16IRQHandler11: + PushF + Call [OldIRQHandler] + +PAS16IRQHandler12: + +DMAPort1 EQU $+1 + In AL, 1 + Mov AH, AL +DMAPort2 EQU $+1 + In AL, 1 + XChg AL, AH + + Mov Debug2, AX + + Cmp MixBufferPos, 0 + JE PAS16IRQHandler13 + + Xor BX, BX +DMABufferLength1 EQU $+1 + Cmp AX, 1234h + JB PAS16IRQHandler1 + + Pop DS + Pop BX + Pop AX + IRet + +PAS16IRQHandler13: + Mov BX, DMABUFFERLENGTH/2 +DMABufferLength2 EQU $+1 + Cmp AX, 1234h + JAE PAS16IRQHandler1 + + Pop DS + Pop BX + Pop AX + IRet + +PAS16IRQHandler1: + Xor MixBufferPos, 1 + + PushAD + Push ES + + CLD + + + ; OK... time to get next block + ; Check whether stereo thing is on.. + ; + LES DI, [ActualDMAPtr] + Add DI, BX + + Mov BX, DMABUFFERLENGTH/4 ; BX = samples required + Mov BP, 8 ; Skip for mono + Mov CL, 14 ; Shift for mono + + Cmp Stereo, 0 + JE PAS16IRQHandlerMono + + Mov BP, 4 ; Stereo skip value. + Dec CL + +PAS16IRQHandlerMono: + Call SaveEMSPageFrame + + Cmp MixTransferRemaining, 0 + JNE PAS16IRQHandler4 + Assume DS:Nothing + +PAS16IRQHandler3: + Push BX + Push CX + Push BP + Push ES + Push DI + + Call Update + Call MixSamples + + Pop DI + Pop ES + Pop BP + Pop CX + Pop BX + +PAS16IRQHandler4: + Mov DS, MixSegment + Mov SI, MixTransferOffset + Mov DX, BX ; DX = samples to transfer + Cmp DX, MixTransferRemaining + JBE PAS16IRQHandler5 + + Mov DX, MixTransferRemaining + +PAS16IRQHandler5: + Push DX + Cmp CS:Filter, 1 + JB PAS16IRQHandler6 + JE PAS16IRQHFilter + + Cmp CS:Stereo, 0 + JE PAS16IRQ3QFilterMono + +PAS16IRQ3QFilterStereo: + Push BX + + Mov EBX, FilterValue + Mov EBP, FilterValue2 + ShR DX, 1 + +PAS16IRQ3QFilterStereo1: + Mov EAX, EBX + Mov ECX, EBP + Add EAX, [SI] + Add ECX, [SI+4] + SAR EAX, 1 + SAR ECX, 1 + Add EBX, EAX + Add EBP, ECX + SAR EBX, 1 + SAR EBP, 1 + + Mov EAX, EBX + SAR EAX, 13 + + Cmp EAX, -8000h + JL PAS163QFilterStereoClip1 + Cmp EAX, 7FFFh + JG PAS163QFilterStereoClip2 + +PAS16IRQ3QFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL PAS163QFilterStereoClip3 + Cmp EAX, 7FFFh + JG PAS163QFilterStereoClip4 + +PAS16IRQ3QFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ PAS16IRQ3QFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp PAS16MixTransferEnd + +PAS16IRQ3QFilterMono: + Push BX + + Mov EBX, FilterValue + +PAS16IRQ3QFilterMono1: + Mov EAX, EBX + Add EAX, [SI] + SAR EAX, 1 + Add EBX, EAX + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL PAS163QFilterMonoClip1 + Cmp EAX, 7FFFh + JG PAS163QFilterMonoClip2 + +PAS16IRQ3QFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ PAS16IRQ3QFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp PAS16MixTransferEnd + +PAS16IRQHFilter: + Cmp CS:Stereo, 0 + JE PAS16IRQHFilterMono + +PAS16IRQHFilterStereo: + Push BX + + Mov EBX, FilterValue + Mov EBP, FilterValue2 + ShR DX, 1 + +PAS16IRQHFilterStereo1: + Add EBX, [SI] + Add EBP, [SI+4] + + SAR EBX, 1 + SAR EBP, 1 + + Mov EAX, EBX + SAR EAX, 13 + + Cmp EAX, -8000h + JL PAS16HFilterStereoClip1 + Cmp EAX, 7FFFh + JG PAS16HFilterStereoClip2 + +PAS16IRQHFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL PAS16HFilterStereoClip3 + Cmp EAX, 7FFFh + JG PAS16HFilterStereoClip4 + +PAS16IRQHFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ PAS16IRQHFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp PAS16MixTransferEnd + +PAS16IRQHFilterMono: + Push BX + + Mov EBX, FilterValue + +PAS16IRQHFilterMono1: + Add EBX, [SI] + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL PAS16HFilterMonoClip1 + Cmp EAX, 7FFFh + JG PAS16HFilterMonoClip2 + +PAS16IRQHFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ PAS16IRQHFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp PAS16MixTransferEnd + +PAS16IRQHandler6: + Mov EAX, [SI] + SAR EAX, CL + + Cmp EAX, -8000h + JL PAS16IRQHandlerClip1 + Cmp EAX, 7FFFh + JG PAS16IRQHandlerClip2 + +PAS16IRQHandler7: + StosW ; } Memory write + + Add SI, BP + Dec DX + JNZ PAS16IRQHandler6 + +PAS16MixTransferEnd: + Pop DX + + Sub MixTransferRemaining, DX ; } Memory write + Sub BX, DX + JNZ PAS16IRQHandler3 + + Mov MixTransferOffset, SI ; } Memory write + + Call RestoreEMSPageFrame + + Pop ES + PopAD + Pop DS + Pop BX + Pop AX + IRet + +PAS16IRQHandlerClip1: + Mov AX, 8000h + Jmp PAS16IRQHandler7 + +PAS16IRQHandlerClip2: + Mov AX, 7FFFh + Jmp PAS16IRQHandler7 + +PAS16HFilterMonoClip1: + Mov AX, 8000h + Jmp PAS16IRQHFilterMono2 + +PAS16HFilterMonoClip2: + Mov AX, 7FFFh + Jmp PAS16IRQHFilterMono2 + +PAS16HFilterStereoClip1: + Mov AX, 8000h + Jmp PAS16IRQHFilterStereo2 + +PAS16HFilterStereoClip2: + Mov AX, 7FFFh + Jmp PAS16IRQHFilterStereo2 + +PAS16HFilterStereoClip3: + Mov AX, 8000h + Jmp PAS16IRQHFilterStereo3 + +PAS16HFilterStereoClip4: + Mov AX, 7FFFh + Jmp PAS16IRQHFilterStereo3 + +PAS163QFilterMonoClip1: + Mov AX, 8000h + Jmp PAS16IRQ3QFilterMono2 + +PAS163QFilterMonoClip2: + Mov AX, 7FFFh + Jmp PAS16IRQ3QFilterMono2 + +PAS163QFilterStereoClip1: + Mov AX, 8000h + Jmp PAS16IRQ3QFilterStereo2 + +PAS163QFilterStereoClip2: + Mov AX, 7FFFh + Jmp PAS16IRQ3QFilterStereo2 + +PAS163QFilterStereoClip3: + Mov AX, 8000h + Jmp PAS16IRQ3QFilterStereo3 + +PAS163QFilterStereoClip4: + Mov AX, 7FFFh + Jmp PAS16IRQ3QFilterStereo3 + +EndP PAS16IRQHandler + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + + Push EAX + Push ES + + Xor AX, AX + Mov ES, AX + + Mov AL, 34h ; Program IRQ 0. LSB&MSB, Rate gen + Out 43h, AL + + ; bump the interrupt to be called + ; 100 times a second. + Mov AX, TIMERCONST + Out 40h, AL + Mov AL, AH + Out 40h, AL + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset PAS16IRQHandler + + ClI + + XChg [ES:20h], EAX ; Hook to timer interrupt + Mov CS:OldIRQHandler, EAX + + StI + + Pop ES + Pop EAX + + Ret + +EndP SetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIRQ + + Push EAX + Push ES + + Xor AX, AX + Mov ES, AX + + Mov AL, 34h ; Program IRQ 0. LSB&MSB, Rate gen + Out 43h, AL + + Xor AL, AL + Out 40h, AL ; Interrupt called at normal 18.2 times + Out 40h, AL + + Mov EAX, CS:OldIRQHandler + Mov [ES:20h], EAX + + Pop ES + Pop EAX + + Ret + +EndP ResetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StopPAS16 + + Mov DX, BasePort + Xor AL, AL + Xor DX, 0B89h xor 388h ; Interrupt Status register + Out DX, AL + + Mov DX, BasePort ; Audio filter control + Mov AL, 1 + Xor DX, 0B8Ah xor 388h ; Disable buffer counter + Out DX, AL ; and PAS 16 output + + Mov DX, BasePort + Xor DX, 8389h xor 388h ; SysConfig2 + In AL, DX ; Get SysConfig2 + And AL, Not 4 ; Reset 8 bits + Out DX, AL + + Mov DX, BasePort + Mov AL, 19h ; Mono, L2L, R2R + Xor DX, 0F8Ah xor 388h ; Cross channel register + Out DX, AL + + Ret + +EndP StopPAS16 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StartPAS16 ; + + PushA + Push ES + Push DS + + Push CS + Pop DS + Assume DS:Driver + + ; Setup DMA + Mov BX, DMASegment + Xor AX, AX + Mov DX, DMA + Mov DI, DMABUFFERLENGTH + Call SetDMA + + LES DI, ActualDMAPtr + Xor AX, AX + Mov CX, DMABUFFERLENGTH/2 + Rep StosW + + Mov MixBufferPos, 0 + Mov MixTransferRemaining, 0 + + Mov DX, BasePort + Xor AL, AL + Xor DX, 0B89h xor 388h ; Interrupt Status register + Out DX, AL + + Mov DX, BasePort ; Audio filter control + Mov AL, 1 + Xor DX, 0B8Ah xor 388h ; Disable buffer counter + Out DX, AL ; and PAS 16 output + + Mov DX, BasePort + Mov AL, 19h + Xor DX, 0F8Ah xor 388h ; Cross channel register + Out DX, AL + + Mov DX, BasePort + Xor DX, 138Bh xor 388h ; Timer control, + Mov AL, 00110110b ; 36h - set frequency + Out DX, AL + + Mov DX, BasePort + Xor DX, 1388h xor 388h + Mov AX, PASMixConst + Cmp Stereo, 0 + JE StartPAS16_2 + + ShR AX, 1 + +StartPAS16_2: + Out DX, AL + Mov AL, AH + Out DX, AL + + Call GetMixSpeed + Call GetTempo + Call SetTempo + + Mov DX, BasePort + Xor DX, 138Bh xor 388h ; Timer control + Mov AL, 01110100b ; 74h - set buffer count + Out DX, AL + + Mov DX, BasePort ; Sample count + Mov AX, DMABUFFERLENGTH + Xor DX, 1389h xor 388h + + Cmp DMA, 4 + JB StartPAS16_1 + + ShR AX, 1 + +StartPAS16_1: + Out DX, AL + Mov AL, AH + Out DX, AL + + Mov DX, BasePort + Xor DX, 8389h xor 388h ; SysConfig2 + In AL, DX ; Get SysConfig2 + Or AL, 4 ; Set 16 bits + Out DX, AL + + Mov AL, Stereo + Xor AL, 1 ; 0 if stereo, 1 if mono. + ShL AL, 5 + Mov DX, BasePort + Or AL, 099h ; Enable DRQ, DAC output + Xor DX, 0F8Ah xor 388h + Out DX, AL + Jmp $+2 + Jmp $+2 + Or AL, 40h ; Enable PCM + Out DX, AL + + Mov DX, BasePort + Xor DX, 0B8Bh xor 388h + In AL, DX + Or AL, 8 ; Enable sample buffer intr + Out DX, AL + + Mov DX, BasePort ; Disable output&timers + Mov AL, 0E1h ; disable mute, enable sample rate + ; timer and sample buffer counter. + Xor DX, 0B8Ah xor 388h + Out DX, AL + + Pop DS + Pop ES + PopA + + Ret + + Assume DS:Nothing + +EndP StartPAS16 + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov SI, Offset RelocationTable + +RelocationFix: + LodsW + Test AX, AX + JZ RelocationEnd + Mov BX, AX + Mov [BX], DS + Jmp RelocationFix + + +RelocationEnd: + Call GetEMSPageFrame + Mov EMSPageFrame, AX + + In AL, 0A1h + Mov AH, AL + In AL, 21h + Mov IMR, AX + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + Call GetPASMixConst + + Mov AX, 2643 + Mul MixSpeed + Add AX, 0FFFFh + AdC DX, 2080 + + Mov BX, (DMABUFFERLENGTH*2)/16 + Add BX, DX + + ; Allocate MixSegment first + Mov AH, 48h + + Int 21h + JNC InitSound1 + +InitSoundNoMemory: + Mov SI, Offset PAS16NoMemoryMsg + Ret + +InitSound1: + Mov MixSegment, AX + Add AX, DX + Mov DMASegment, AX + + Call SetIRQ + Call GetTempo + Call SetTempo + + Mov SI, Offset PAS16Msg + + Mov AX, BasePort + Mov BX, IRQ + Mov CX, DMA + + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Call ResetIRQ + Call SetIRQ + + Mov SI, Offset ReInitMsg + Mov BX, 40 + Call SetInfoLine + + Mov AL, Stereo + Call SetStereo + + Pop ES + Pop DS + PopA + + Ret + +EndP ReInitSound + Assume DS:Nothing + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, IMR + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Mov AX, MixSegment + Test AX, AX + JZ UnInitSound1 + + Mov ES, AX + Mov AH, 49h ; Release MixSegment + Int 21h + + Call StopPAS16 + Call ResetIRQ + +UnInitSound1: + Ret + +EndP UnInitSound + Assume DS:Nothing + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + +; In AL, 1 +; Mov AH, AL +; In AL, 1 +; Mov CS:Debug2, AX + + Ret + +EndP Poll + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Push AX + Push BX + Push DX + + Push BX + + Mov AX, MixSpeed + Mov BX, AX + Xor DX, DX + + ShL AX, 1 + RCL DX, 1 ; DX:AX = Mixspeed*2 + + ShR BX, 1 ; BX = Mixspeed/2 + + Add AX, BX + AdC DX, 0 ; DX:AX = Mixspeed*2.5 + + Pop BX ; BX = tempo + Div BX + + Mov BytesToMix, AX + + Pop DX + Pop BX + Pop AX + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + PushA + Push DS + + Mov BX, AX ; BX = MixVolume + Mov CS:MixVolume, BX + + Mov AX, CS:MixSegment + Test AX, AX + JZ SetMixVolume2 + + Mov DS, AX + + Mov CX, MIXTABLESIZE/2 + Mov SI, MIXTABLESIZE-2; Starting point - working backwards + +SetMixVolume1: + Mov AX, CX + + Dec AX ; AH = volume, AL = wave value. + Xor DX, DX + XChg AH, DL ; DL = Volume, AX = wave value + CBW + + IMul DX ; DX:AX = Volume * Wave Value + ; Ranges -8192->8128 + + IMul BX ; DX:AX = Volume * Wave Value * Mixing Volume + ; Ranges -1048576->1040384 + + Add AX, 64 + AdC DX, 0 + + ShRD AX, DX, 7 + Mov [SI], AX + Sub SI, 2 + + Loop SetMixVolume1 + +SetMixVolume2: + Call RecalculateAllVolumes + + Pop DS + PopA + + Ret + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc RecalculateAllFrequencies + + Call GetChannelTables + +RecalculateAllFrequencies1: + Or Byte Ptr [SI], 32 + + Add SI, 128 + Dec CX + JNZ RecalculateAllFrequencies1 + + Ret + +EndP RecalculateAllFrequencies + + +Proc SetStereo Far + + Mov CS:Stereo, AL + Cmp CS:MixSegment, 0 + JE SetStereo1 + + Call StopPAS16 + Call StartPAS16 + + Call RecalculateAllFrequencies + +SetStereo1: + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include loadsam.inc + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset PAS16ScreenList + + ClC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far ; Returns AX, given DI + + Xor AH, AH + Mov AL, [CS:VolumeTable+DI] + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far ; Given AX, DI + + Push DS + Push DX + + Push CS + Pop DS + Assume DS:Driver + + Mov [VolumeTable+DI], AL + + Comment ~ + + Mov DX, BasePort + Add DL, 4 + Mov AL, 30h + Mov AH, [VolumeTable] + ShL AH, 3 + Out DX, AX + + Mov AL, 31h + Mov AH, [VolumeTable+1] + ShL AH, 3 + Out DX, AX + + Mov AL, 44h + Mov AH, [VolumeTable+2] + ShL AH, 4 + Out DX, AX + + Mov AL, 45h + Mov AH, [VolumeTable+3] + ShL AH, 4 + Out DX, AX + + Mov AL, 46h + Mov AH, [VolumeTable+4] + ShL AH, 4 + Out DX, AX + + Mov AL, 47h + Mov AH, [VolumeTable+5] + ShL AH, 4 + Out DX, AX + + ~ + + Pop DX + Pop DS + Ret + +EndP SetVariable + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. + +StopAfterPlay DW 0 +DefaultChannels DW 64 + DW 5 Dup (0) + + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/PASDRV.ASM b/SoundDrivers/PASDRV.ASM new file mode 100755 index 0000000..5c79d1c --- /dev/null +++ b/SoundDrivers/PASDRV.ASM @@ -0,0 +1,1903 @@ + + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;********************************** + +STEREOENABLED EQU 1 +DMABUFFERLENGTH EQU 4096 +MIXRESOLUTION EQU 16 ; 32 bit mixing for the PAS16 +MIXTABLESIZE EQU 2*256*65 +TIMERCONST EQU 11932 + +Debug1 DB 0 +Debug2 DW 0 + +PAS16Msg DB "Pro Audio Spectrum found", 13 + DB "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, DMA ", 0FDh, "D", 0 + +PAS16NoMemoryMsg DB "Pro Audio Spectrum found", 13 + DB "Error: Insufficient memory", 0 + +ReinitMsg DB "Pro Audio Spectrum reinitialised", 0 + +ConfigErrorMsg DB "Error saving configuration to ITPAS.DRV", 0 +ConfigOKMsg DB "Configuration saved to ITPAS.DRV", 0 + +DriverName DB "ITPAS.DRV", 0 + +Forced DB 0 +Stereo DB 0 +MixVolume DW 0 + +BytesToMix DW 1000 +MixSpeed DW 44100 +PASMixConst DW 0 + +MixSegment DW 0 +DMASegment DW 0 + +MixTransferOffset DW 0 +MixTransferRemaining DW 0 + +CONFIGURATIONOFFSET EQU $+128 +CONFIGSIZE EQU 6 +MixMode DW 0 +MixModeOffset DW 0 +Filter DW 0 + +IMR DW 0 +OldIRQHandler DD 0 + +FilterValue DW 0 +FilterValue2 DW 0 +TimerAccumulator DW 0 + +DMALengthTable Label Byte + DB 1, 3, 5, 7, 0C2h, 0C6h, 0CAh, 0CEh + +;********************************** + +PAS16ScreenList Label + DW 6 + DW Near Ptr IdleFunctionList + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr PASHeaderLine + + DW Near Ptr DriverText + + DW Near Ptr MixModeText + DW Near Ptr MixModeButton1 ; 6 + DW Near Ptr MixModeButton2 ; 7 + + DW Near Ptr FilterText + DW Near Ptr FilterButton1 ; 9 + DW Near Ptr FilterButton2 + DW Near Ptr FilterButton3 + + DW 0 + +PASHeaderLine DW 10 + DB "Pro Audio Spectrum Driver", 0 + +EmptyObject DW 1 + DB 0, 0 + DB 0 + DB 0 + +DriverText DW 1 + DB 29, 48 + DB 21h + DB "Pro Audio Spectrum Driver 1.0 for Impulse Tracker", 0 + +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +IdleFunctionList DD 0 + DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +MixModeText DW 1 + DB 2, 13 + DB 20h + DB "Mixing Mode", 0 + +MixModeButton1 DW 2 + DW 0FFFFh, 7, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment1 DW 0 + DW 0 + DW Offset SetMixMode +DriverSegment2 DW 0 + DB 3, 15, 32, 17, 8 + DB 0 + DB " 16 Bit, Non-Interpolated", 0 + +MixModeButton2 DW 2 + DW 6, 9, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment3 DW 0 + DW 2 + DW Offset SetMixMode +DriverSegment4 DW 0 + DB 3, 18, 32, 20, 8 + DB 0 + DB " 16 Bit, Interpolated", 0 + +FilterText DW 1 + DB 2, 22 + DB 20h + DB "Filter mode", 0 + +FilterButton1 DW 2 + DW 7, 10, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment9 DW 0 + DW 0 + DW Offset SetFilter +DriverSegment10 DW 0 + DB 3, 24, 29, 26, 8 + DB 0 + DB " No Filter", 0 + +FilterButton2 DW 2 + DW 9, 11, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment11 DW 0 + DW 1 + DW Offset SetFilter +DriverSegment12 DW 0 + DB 3, 27, 29, 29, 8 + DB 0 + DB " 50% Filter", 0 + +FilterButton3 DW 2 + DW 10, 0FFFFh, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment13 DW 0 + DW 2 + DW Offset SetFilter +DriverSegment14 DW 0 + DB 3, 30, 29, 32, 8 + DB 0 + DB " 75% Filter", 0 + +VolumeTable DB 6 Dup (0) + +; ÄÄ MixingRoutines ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixBufferPos DW 0 + +include dma.inc +include mix.inc +include m12bit.mix +include m12biti.mix + +MixFunctionTables Label + +include m12bit.inc ; contains the tables +include m12biti.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +RelocationTable Label Word + DW Offset DriverSegment1, Offset DriverSegment2 + DW Offset DriverSegment3, Offset DriverSegment4 + DW Offset DriverSegment9, Offset DriverSegment10 + DW Offset DriverSegment11, Offset DriverSegment12 + DW Offset DriverSegment13, Offset DriverSegment14 + DW 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixMode Far + + Push CS + Pop ES + Mov DI, Offset MixMode + + Ret + +EndP GetMixMode + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetFilter Far + + Push CS + Pop ES + Mov DI, Offset Filter + + Ret + +EndP GetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetFilter Far + + Mov AX, [SI+22] + Mov CS:FilterValue, 0 + Mov CS:Filter, AX + ClI + Jmp SetMixModeChain + +EndP SetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixMode Far + + Mov AX, [SI+22] + + ClI + + Mov CS:MixMode, AX + + Mov BX, 180 + Mul BX + Mov CS:MixModeOffset, AX + + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS:RecalculateAllVolumes + + StI + +SetMixModeChain: + Call GotoHomeDirectory + + ; Now to save config into driver file. + Push CS + Pop DS + Assume DS:Driver + + Mov AX, 3D02h ; Read write access + Mov DX, Offset DriverName + Mov SI, Offset ConfigErrorMsg + Int 21h + JC SetMixMode1 + + Mov BX, AX + + Mov AX, 4200h + Xor CX, CX + Mov DX, Offset CONFIGURATIONOFFSET + Int 21h + JC SetMixMode2 + + Mov AH, 40h + Mov CX, CONFIGSIZE + Mov DX, Offset MixMode + Int 21h + +SetMixMode2: + PushF + Mov AH, 3Eh + Int 21h + PopF + + JC SetMixMode1 + + Mov SI, Offset ConfigOKMsg + +SetMixMode1: + Mov BX, 40 + Call SetInfoLine + + Mov AX, 1 + Ret + +EndP SetMixMode + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixSpeed + Assume DS:Driver + + Push AX + Push CX + Push DX + + Mov DX, 12h + Mov AX, 34DCh + Mov CX, PASMixConst + Cmp CS:Stereo, 0 + JE GetMixSpeed1 + + And CX, Not 1 + +GetMixSpeed1: + Div CX + +GetMixSpeed2: + Mov MixSpeed, AX + + Pop DX + Pop CX + Pop AX + Ret + +EndP GetMixSpeed + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetPASMixConst ; Work out value.. and nearest + ; mixspeed value. + + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, CmdLineMixSpeed + Mov CX, MixSpeed + Test AX, AX + JZ GetPASMixConst1 + + Mov CX, 44100 + Cmp AX, CX + JA GetPASMixConst1 + + Mov CX, 12000 + Cmp AX, CX + JB GetPASMixConst1 + + Mov CX, AX + +GetPASMixConst1: + Mov MixSpeed, CX + + Mov DX, 012h + Mov AX, 34DCh + Div CX + + Mov PASMixConst, AX + Mov BX, AX + + Pop DS + PopA + Ret + +EndP GetPASMixConst + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc TestPAS ; AX = port + + Push AX + + Mov DX, 803h ; Default is 0B8Bh + Xor DX, AX ; DX = Interrupt Control port + In AL, DX + + Cmp AL, 0FFh + JE TestPAS1 + + Mov AH, AL + Xor AL, 11100000b + Out DX, AL + + Jmp $+2 + Jmp $+2 + In AL, DX + + Cmp AL, AH + XChg AH, AL + Out DX, AL + JNE TestPAS1 + + Pop AX + + ClC + Ret + +TestPAS1: + Pop AX + StC + Ret + +EndP TestPAS + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, 0BC00h + Mov BX, '??' + Xor CX, CX + Xor DX, DX + Int 2Fh + + Xor BX, CX + Xor BX, DX + Cmp BX, 'M'*256+'V' + JE DetectPAS4 ; MVSound.Sys installed! + +DetectPAS7: + StC + Ret + +DetectPAS4: + Mov AX, BasePort + Cmp AX, 0FFFFh + JE DetectPAS1 + Cmp AX, 388h + JE DetectPAS6 + Cmp AX, 384h + JE DetectPAS6 + Cmp AX, 38Ch + JE DetectPAS6 + Cmp AX, 288h + JNE DetectPAS7 + +DetectPAS6: + Call TestPAS + JNC DetectPAS2 + + Ret + +DetectPAS1: + Mov AX, 388h + Call TestPAS + JNC DetectPAS2 + + Mov AX, 384h + Call TestPAS + JNC DetectPAS2 + + Mov AX, 38Ch + Call TestPAS + JNC DetectPAS2 + + Mov AX, 288h + Call TestPAS + JNC DetectPAS2 + + Ret ; No card! + +DetectPAS2: + Push AX + + Mov AX, 0BC04h + Int 2Fh + + Cmp AX, 'M'*256+'V' + JNE DetectPAS3 + + Pop AX + + Mov BasePort, AX + Mov DMA, BX + Mov IRQ, CX + + Mov AL, [DMALengthTable+BX] + Mov Byte Ptr [DMAPort1], AL + Mov Byte Ptr [DMAPort2], AL + + Mov AX, DMABUFFERLENGTH/2 + Cmp BX, 4 + JB DetectPAS5 + + ShR AX, 1 + +DetectPAS5: + Mov Word Ptr [DMABufferLength1], AX + Mov Word Ptr [DMABufferLength2], AX + + Mov EAX, 'Jeff' + + ClC + Ret + +DetectPAS3: + Pop AX + StC + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixModeTable Label Word + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + +Proc MixSamples ; Given DS:SI = info tables, CX = numchannels + + ; 1. Clean buffer + ; + update variables + ; 2. Update parameters + ; 3. Mix func + ; 4. Return + + Push CX + + Mov CX, BytesToMix + Mov ES, MixSegment + Mov DI, MIXTABLESIZE + Mov AX, 2020h + Mov DX, CX + Add CX, CX + + Mov MixTransferOffset, DI ; } Memory write + + Cmp Stereo, 0 + JE MixSamples1 + + ShR AX, 1 + Mov DX, CX + +MixSamples1: + Rep StosW ; } Memory write + Mov MixTransferRemaining, DX ; } + + Pop CX + +MixSamples2: + Test Byte Ptr [SI], 1 + JZ MixSamplesEnd2 + Cmp Byte Ptr [SI+36h], 100 + JE MixSamplesEnd2 + + Push CX + Mov CX, [SI] + + Test CH, 2 + JZ MixSamples3 + And Byte Ptr [SI], Not 1 + + Jmp MixSamplesEnd +; Cmp MixMode, 8 ; Is it volume ramping? +; JB MixSamplesEnd + +MixSamples3: + Test CL, 20h ; New freq? + JZ MixSamples5 + + Mov AX, [SI+10h] + Mov DX, [SI+12h] + Mov BX, MixSpeed + Cmp DX, BX + JAE MixSamplesHandleError + + Div BX + ShL EAX, 16 + Xor AX, AX + Div BX + Mov STEPVALUE, EAX + +MixSamples4: + Test CH, 1 + JZ MixSamples5 + + Mov DWord Ptr [SI+1Ch], 0 ; Current Volume = 0 + ; for volume sliding. +MixSamples5: + Test CX, 8440h ; New volume or panning? + JZ MixSamplesMix + + Xor AX, AX + Test CH, 8 ; Muted? + JNZ MixModeCommon + + Mov BX, MixMode + Add BL, Stereo + Add BX, BX + Jmp [CS:MixModeTable+BX] + +Mix0Mode: ; 16-bit mixing, no interpolation +Mix0ModeMono: ; and 16-bit mixing, interpolation + Mov AL, [SI+20h] + ShR AL, 1 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 30 ; Use left only-mixing for mono + Jmp MixModeCommon + +Mix0ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix0ModeSurround + + Mul Byte Ptr [SI+20h] ; Final volume + Add AX, 64 + ShR AX, 7 + Mov [SI+0Ch], AX ; Store into right volume + + Mov AL, 64 + Sub AL, [SI+37h] + Mul Byte Ptr [SI+20h] + Add AX, 64 + ShR AX, 7 + Mov [SI+0Eh], AX ; Left volume + + Mov CH, AL ; CH = left volume + Mov CL, [SI+0Ch] ; CL = right volume + Mov AX, 0 + + Test CX, CX + JZ MixModeCommon + + Mov AL, 30 ; Left only... + Test CL, CL + JZ MixModeCommon + + Mov AL, 60 + Test CH, CH + JZ MixModeCommon + + Mov AL, 90 + Cmp CL, CH + JZ MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix0ModeSurround: + Mov AL, [SI+20h] + ShR AL, 2 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 150 ; Surround + Jmp MixModeCommon + +Mix6ModeMono: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 8 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Test AX, AX + JZ MixModeCommon + Mov AX, 30 + Jmp MixModeCommon + +Mix6ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix6ModeSurround + + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Ch], AX ; Store into right volume + Mov BX, AX + ShL EAX, 16 + + Mov AL, 64 ; Do left volume + Sub AL, [SI+37h] ; AL = 64-FinalPan + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Eh], AX + + Mov ECX, EAX + + ; BX = right volume + ; CX = Left volume + Mov AX, 0 + Test ECX, ECX + JZ MixModeCommon + + Mov AL, 30 + Test BX, BX + JZ MixModeCommon + + Mov AL, 60 + Test CX, CX + JZ MixModeCommon + + Mov AL, 90 + Cmp CX, BX + JE MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix6ModeSurround: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 9 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + JZ MixModeCommon + Mov AX, 150 + Jmp MixModeCommon + +MixModeCommon: ; Requires AX = 30/60/90 etc. depending + ; On mixing mode type. + ; This will add 180 for 16-bit, + ; And sort out loop types. + Mov BL, [SI+0Ah] + Test Byte Ptr [SI+18h], 2 ; 16 bit? + JZ MixModeCommon1 + + Add AX, 180 + +MixModeCommon1: + Cmp BL, 8 + JB MixModeCommon3 ; No loop + JE MixModeCommon2 ; Forwards loop + + Add AX, 10 + +MixModeCommon2: + Add AX, 10 + +MixModeCommon3: + Add AX, Offset MixFunctionTables + Add AX, MixModeOffset + Mov [SI+8], AX ; Offset... + +MixSamplesMix: + Mov BX, [SI+8] ; BX = offset into + Mov EAX, [CS:BX+2] + Mov DWord Ptr PreMixFunction, EAX + Mov EAX, [CS:BX+6] + Mov DWord Ptr MixFunctionSeparateBackwards, EAX + + Mov AX, BytesToMix + Mov MixBlockSize, AX + Mov MixBufferOffset, MIXTABLESIZE + + Mov EAX, CURRENTPOSITION + Mov OLDPOSITION, EAX + + Call Word Ptr [CS:BX] + + And Word Ptr [SI], 0111100010001101b + Jmp MixSamplesEnd + +MixSamplesHandleError: + Mov Word Ptr [SI], 200h + + Test Byte Ptr [SI+3Ah], 80h + JNZ MixSamplesEnd + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Turn off channel + +MixSamplesEnd: + Pop CX + +MixSamplesEnd2: + Add SI, 128 + Dec CX + JNZ MixSamples2 + + Ret + +EndP MixSamples + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PAS16IRQHandler + + Push AX + Push BX + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Add TimerAccumulator, TIMERCONST + JC PAS16IRQHandler11 + + Mov AL, 20h + Out 20h, AL + Jmp PAS16IRQHandler12 + +PAS16IRQHandler11: + PushF + Call [OldIRQHandler] + +PAS16IRQHandler12: + +DMAPort1 EQU $+1 + In AL, 1 + Mov AH, AL +DMAPort2 EQU $+1 + In AL, 1 + XChg AL, AH + + Mov Debug2, AX + + Cmp MixBufferPos, 0 + JE PAS16IRQHandler13 + + Xor BX, BX +DMABufferLength1 EQU $+1 + Cmp AX, 1234h + JB PAS16IRQHandler1 + + Pop DS + Pop BX + Pop AX + IRet + +PAS16IRQHandler13: + Mov BX, DMABUFFERLENGTH/2 +DMABufferLength2 EQU $+1 + Cmp AX, 1234h + JAE PAS16IRQHandler1 + + Pop DS + Pop BX + Pop AX + IRet + +PAS16IRQHandler1: + Xor MixBufferPos, 1 + + PushAD + Push ES + + CLD + + + ; OK... time to get next block + ; Check whether stereo thing is on.. + ; + LES DI, [ActualDMAPtr] + Add DI, BX + + Mov BX, DMABUFFERLENGTH/2 ; BX = samples required + Mov BP, 4 ; Skip for mono + Mov CL, 6 ; Shift for mono + + Cmp Stereo, 0 + JE PAS16IRQHandlerMono + + Mov BP, 2 ; Stereo skip value. + Dec CL + +PAS16IRQHandlerMono: + Call SaveEMSPageFrame + + Cmp MixTransferRemaining, 0 + JNE PAS16IRQHandler4 + Assume DS:Nothing + +PAS16IRQHandler3: + Push BX + Push CX + Push BP + Push ES + Push DI + + Call Update + Call MixSamples + + Pop DI + Pop ES + Pop BP + Pop CX + Pop BX + +PAS16IRQHandler4: + Mov DS, MixSegment + Mov SI, MixTransferOffset + Mov DX, BX ; DX = samples to transfer + Cmp DX, MixTransferRemaining + JBE PAS16IRQHandler5 + + Mov DX, MixTransferRemaining + +PAS16IRQHandler5: + Push DX + Cmp CS:Filter, 1 + JB PAS16IRQHandler6 + JE PAS16IRQHFilter + + Cmp CS:Stereo, 0 + JE PAS16IRQ3QFilterMono + +PAS16IRQ3QFilterStereo: + Push BX + + Mov BX, FilterValue + Mov BP, FilterValue2 + ShR DX, 1 + +PAS16IRQ3QFilterStereo1: + Mov AX, BX + Mov CX, BP + Add AX, [SI] + Add CX, [SI+2] + SAR AX, 1 + SAR CX, 1 + Add BX, AX + Add BP, CX + SAR BX, 1 + SAR BP, 1 + + Mov AX, BX + SAR AX, 5 + + Test AH, AH + JNZ PAS163QFilterStereoClip1 + +PAS16IRQ3QFilterStereo2: + StosB + + Mov AX, BP + SAR AX, 5 + + Test AH, AH + JNZ PAS163QFilterStereoClip3 + +PAS16IRQ3QFilterStereo3: + StosB + + Add SI, 4 + Dec DX + JNZ PAS16IRQ3QFilterStereo1 + + Mov FilterValue, BX + Mov FilterValue2, BP + + Pop BX + + Jmp PAS16MixTransferEnd + +PAS16IRQ3QFilterMono: + Push BX + + Mov BX, FilterValue + +PAS16IRQ3QFilterMono1: + Mov AX, BX + Add AX, [SI] + SAR AX, 1 + Add BX, AX + SAR BX, 1 + Mov AX, BX + SAR AX, 6 + + Test AH, AH + JNZ PAS163QFilterMonoClip1 + +PAS16IRQ3QFilterMono2: + StosB + + Add SI, 4 + Dec DX + JNZ PAS16IRQ3QFilterMono1 + + Mov FilterValue, BX + + Pop BX + + Jmp PAS16MixTransferEnd + +PAS16IRQHFilter: + Cmp CS:Stereo, 0 + JE PAS16IRQHFilterMono + +PAS16IRQHFilterStereo: + Push BX + + Mov BX, FilterValue + Mov BP, FilterValue2 + ShR DX, 1 + +PAS16IRQHFilterStereo1: + Add BX, [SI] + Add BP, [SI+2] + + SAR BX, 1 + SAR BP, 1 + + Mov AX, BX + SAR AX, 5 + + Test AH, AH + JNZ PAS16HFilterStereoClip1 + +PAS16IRQHFilterStereo2: + StosB + + Mov AX, BP + SAR AX, 5 + + Test AH, AH + JNZ PAS16HFilterStereoClip3 + +PAS16IRQHFilterStereo3: + StosB + + Add SI, 4 + Dec DX + JNZ PAS16IRQHFilterStereo1 + + Mov FilterValue, BX + Mov FilterValue2, BP + + Pop BX + + Jmp PAS16MixTransferEnd + +PAS16IRQHFilterMono: + Push BX + + Mov BX, FilterValue + +PAS16IRQHFilterMono1: + Add BX, [SI] + SAR BX, 1 + Mov AX, BX + SAR AX, 6 + + Test AH, AH + JNZ PAS16HFilterMonoClip1 + +PAS16IRQHFilterMono2: + StosB + + Add SI, 4 + Dec DX + JNZ PAS16IRQHFilterMono1 + + Mov FilterValue, BX + + Pop BX + + Jmp PAS16MixTransferEnd + +PAS16IRQHandler6: + Mov AX, [SI] + SAR AX, CL + + Test AH, AH + JNZ PAS16IRQHandlerClip1 + +PAS16IRQHandler7: + StosB ; } Memory write + + Add SI, BP + Dec DX + JNZ PAS16IRQHandler6 + +PAS16MixTransferEnd: + Pop DX + + Sub MixTransferRemaining, DX ; } Memory write + Sub BX, DX + JNZ PAS16IRQHandler3 + + Mov MixTransferOffset, SI ; } Memory write + + Call RestoreEMSPageFrame + + Pop ES + PopAD + Pop DS + Pop BX + Pop AX + IRet + +PAS16IRQHandlerClip1: + Mov AL, 0FFh + JNS PAS16IRQHandler7 + Mov AL, 0 + Jmp PAS16IRQHandler7 + +PAS16HFilterMonoClip1: + Mov AL, 0FFh + JNS PAS16IRQHFilterMono2 + Mov AL, 0 + Jmp PAS16IRQHFilterMono2 + +PAS16HFilterStereoClip1: + Mov AL, 0FFh + JNS PAS16IRQHFilterStereo2 + Mov AL, 0 + Jmp PAS16IRQHFilterStereo2 + +PAS16HFilterStereoClip3: + Mov AL, 0FFh + JNS PAS16IRQHFilterStereo3 + Mov AL, 0 + Jmp PAS16IRQHFilterStereo3 + +PAS163QFilterMonoClip1: + Mov AL, 0FFh + JNS PAS16IRQ3QFilterMono2 + Mov AL, 0 + Jmp PAS16IRQ3QFilterMono2 + +PAS163QFilterStereoClip1: + Mov AL, 0FFh + JNS PAS16IRQ3QFilterStereo2 + Mov AL, 0 + Jmp PAS16IRQ3QFilterStereo2 + +PAS163QFilterStereoClip3: + Mov AL, 0FFh + JNS PAS16IRQ3QFilterStereo3 + Mov AL, 0 + Jmp PAS16IRQ3QFilterStereo3 + +EndP PAS16IRQHandler + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + + Push EAX + Push ES + + Xor AX, AX + Mov ES, AX + + Mov AL, 34h ; Program IRQ 0. LSB&MSB, Rate gen + Out 43h, AL + + ; bump the interrupt to be called + ; 100 times a second. + Mov AX, TIMERCONST + Out 40h, AL + Mov AL, AH + Out 40h, AL + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset PAS16IRQHandler + + ClI + + XChg [ES:20h], EAX ; Hook to timer interrupt + Mov CS:OldIRQHandler, EAX + + StI + + Pop ES + Pop EAX + + Ret + +EndP SetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIRQ + + Push EAX + Push ES + + Xor AX, AX + Mov ES, AX + + Mov AL, 34h ; Program IRQ 0. LSB&MSB, Rate gen + Out 43h, AL + + Xor AL, AL + Out 40h, AL ; Interrupt called at normal 18.2 times + Out 40h, AL + + Mov EAX, CS:OldIRQHandler + Mov [ES:20h], EAX + + Pop ES + Pop EAX + + Ret + +EndP ResetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StopPAS16 + + Mov DX, BasePort + Xor AL, AL + Xor DX, 0B89h xor 388h ; Interrupt Status register + Out DX, AL + + Mov DX, BasePort ; Audio filter control + Mov AL, 1 + Xor DX, 0B8Ah xor 388h ; Disable buffer counter + Out DX, AL ; and PAS 16 output + + Mov DX, BasePort + Mov AL, 19h ; Mono, L2L, R2R + Xor DX, 0F8Ah xor 388h ; Cross channel register + Out DX, AL + + Ret + +EndP StopPAS16 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StartPAS16 ; + + PushA + Push ES + Push DS + + Push CS + Pop DS + Assume DS:Driver + + ; Setup DMA + Mov BX, DMASegment + Xor AX, AX + Mov DX, DMA + Mov DI, DMABUFFERLENGTH + Call SetDMA + + LES DI, ActualDMAPtr + Xor AX, AX + Mov CX, DMABUFFERLENGTH/2 + Rep StosW + + Mov MixBufferPos, 0 + Mov MixTransferRemaining, 0 + + Mov DX, BasePort + Xor AL, AL + Xor DX, 0B89h xor 388h ; Interrupt Status register + Out DX, AL + + Mov DX, BasePort ; Audio filter control + Mov AL, 1 + Xor DX, 0B8Ah xor 388h ; Disable buffer counter + Out DX, AL ; and PAS 16 output + + Mov DX, BasePort + Mov AL, 19h + Xor DX, 0F8Ah xor 388h ; Cross channel register + Out DX, AL + + Mov DX, BasePort + Xor DX, 138Bh xor 388h ; Timer control, + Mov AL, 00110110b ; 36h - set frequency + Out DX, AL + + Mov DX, BasePort + Xor DX, 1388h xor 388h + Mov AX, PASMixConst + Cmp Stereo, 0 + JE StartPAS16_2 + + ShR AX, 1 + +StartPAS16_2: + Out DX, AL + Mov AL, AH + Out DX, AL + + Call GetMixSpeed + Call GetTempo + Call SetTempo + + Mov DX, BasePort + Xor DX, 138Bh xor 388h ; Timer control + Mov AL, 01110100b ; 74h - set buffer count + Out DX, AL + + Mov DX, BasePort ; Sample count + Mov AX, DMABUFFERLENGTH + Xor DX, 1389h xor 388h + + Cmp DMA, 4 + JB StartPAS16_1 + + ShR AX, 1 + +StartPAS16_1: + Out DX, AL + Mov AL, AH + Out DX, AL + + Mov AL, Stereo + Xor AL, 1 ; 0 if stereo, 1 if mono. + ShL AL, 5 + Mov DX, BasePort + Or AL, 099h ; Enable DRQ, DAC output + Xor DX, 0F8Ah xor 388h + Out DX, AL + Jmp $+2 + Jmp $+2 + Or AL, 40h ; Enable PCM + Out DX, AL + + Mov DX, BasePort + Xor DX, 0B8Bh xor 388h + In AL, DX + Or AL, 8 ; Enable sample buffer intr + Out DX, AL + + Mov DX, BasePort + Mov AL, 0E1h ; disable mute, enable sample rate + ; timer and sample buffer counter. + Xor DX, 0B8Ah xor 388h + Out DX, AL + + Pop DS + Pop ES + PopA + + Ret + + Assume DS:Nothing + +EndP StartPAS16 + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov SI, Offset RelocationTable + +RelocationFix: + LodsW + Test AX, AX + JZ RelocationEnd + Mov BX, AX + Mov [BX], DS + Jmp RelocationFix + + +RelocationEnd: + Call GetEMSPageFrame + Mov EMSPageFrame, AX + + In AL, 0A1h + Mov AH, AL + In AL, 21h + Mov IMR, AX + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + Call GetPASMixConst + ; Parags to allocate = (4/(.4*31*16))*MixSpeed + 2080 + ; = 661*MixSpeed/65536 + + Mov AX, 1322 + Mul MixSpeed + Add AX, 0FFFFh + AdC DX, 2080 + + Mov BX, (DMABUFFERLENGTH*2)/16 + Add BX, DX + + ; Allocate MixSegment first + Mov AH, 48h + + Int 21h + JNC InitSound1 + +InitSoundNoMemory: + Mov SI, Offset PAS16NoMemoryMsg + Ret + +InitSound1: + Mov MixSegment, AX + Add AX, DX + Mov DMASegment, AX + + Call SetIRQ + Call GetTempo + Call SetTempo + + Mov SI, Offset PAS16Msg + + Mov AX, BasePort + Mov BX, IRQ + Mov CX, DMA + + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Call ResetIRQ + Call SetIRQ + + Mov SI, Offset ReInitMsg + Mov BX, 40 + Call SetInfoLine + + Mov AL, Stereo + Call SetStereo + + Pop ES + Pop DS + PopA + + Ret + +EndP ReInitSound + Assume DS:Nothing + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, IMR + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Mov AX, MixSegment + Test AX, AX + JZ UnInitSound1 + + Mov ES, AX + Mov AH, 49h ; Release MixSegment + Int 21h + + Call StopPAS16 + Call ResetIRQ + +UnInitSound1: + Ret + +EndP UnInitSound + Assume DS:Nothing + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + +; In AL, 1 +; Mov AH, AL +; In AL, 1 +; Mov CS:Debug2, AX + + Ret + +EndP Poll + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Push AX + Push BX + Push DX + + Push BX + + Mov AX, MixSpeed + Mov BX, AX + Xor DX, DX + + ShL AX, 1 + RCL DX, 1 ; DX:AX = Mixspeed*2 + + ShR BX, 1 ; BX = Mixspeed/2 + + Add AX, BX + AdC DX, 0 ; DX:AX = Mixspeed*2.5 + + Pop BX ; BX = tempo + Div BX + + Mov BytesToMix, AX + + Pop DX + Pop BX + Pop AX + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + PushA + Push DS + + Mov BX, AX ; BX = MixVolume + Mov CS:MixVolume, BX + + Mov AX, CS:MixSegment + Test AX, AX + JZ SetMixVolume2 + + Mov DS, AX + + Mov CX, MIXTABLESIZE/2 + Mov SI, MIXTABLESIZE-2; Starting point - working backwards + +SetMixVolume1: + Mov AX, CX + + Dec AX ; AH = volume, AL = wave value. + Xor DX, DX + XChg AH, DL ; DL = Volume, AX = wave value + CBW + + IMul DX ; DX:AX = Volume * Wave Value + ; Ranges -8192->8128 + + IMul BX ; DX:AX = Volume * Wave Value * Mixing Volume + ; Ranges -1048576->1040384 + + Add AX, 64 + AdC DX, 0 + + ShRD AX, DX, 7 + Mov [SI], AX + Sub SI, 2 + + Loop SetMixVolume1 + +SetMixVolume2: + Pop DS + PopA + + Ret + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc RecalculateAllFrequencies + + Call GetChannelTables + +RecalculateAllFrequencies1: + Or Byte Ptr [SI], 32 + + Add SI, 128 + Dec CX + JNZ RecalculateAllFrequencies1 + + Ret + +EndP RecalculateAllFrequencies + + +Proc SetStereo Far + + Mov CS:Stereo, AL + Cmp CS:MixSegment, 0 + JE SetStereo1 + + Call StopPAS16 + Call StartPAS16 + + Call RecalculateAllFrequencies + +SetStereo1: + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include loadsam.inc + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset PAS16ScreenList + + ClC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far ; Returns AX, given DI + + Xor AH, AH + Mov AL, [CS:VolumeTable+DI] + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far ; Given AX, DI + + Push DS + Push DX + + Push CS + Pop DS + Assume DS:Driver + + Mov [VolumeTable+DI], AL + + Comment ~ + + Mov DX, BasePort + Add DL, 4 + Mov AL, 30h + Mov AH, [VolumeTable] + ShL AH, 3 + Out DX, AX + + Mov AL, 31h + Mov AH, [VolumeTable+1] + ShL AH, 3 + Out DX, AX + + Mov AL, 44h + Mov AH, [VolumeTable+2] + ShL AH, 4 + Out DX, AX + + Mov AL, 45h + Mov AH, [VolumeTable+3] + ShL AH, 4 + Out DX, AX + + Mov AL, 46h + Mov AH, [VolumeTable+4] + ShL AH, 4 + Out DX, AX + + Mov AL, 47h + Mov AH, [VolumeTable+5] + ShL AH, 4 + Out DX, AX + + ~ + + Pop DX + Pop DS + Ret + +EndP SetVariable + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. + +StopAfterPlay DW 0 +DefaultChannels DW 64 + DW 5 Dup (0) + + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/PCSPKDRV.ASM b/SoundDrivers/PCSPKDRV.ASM new file mode 100755 index 0000000..3e40cd8 --- /dev/null +++ b/SoundDrivers/PCSPKDRV.ASM @@ -0,0 +1,934 @@ + + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;********************************** + +STEREOENABLED EQU 0 +DMABUFFERLENGTH EQU 4096 +MIXRESOLUTION EQU 16 ; 16 bit mixing for the SB Pro +MIXTABLESIZE EQU 2*256*65 + +SBProMsg DB " Using Internal PC Speaker", 0 + +SBProNoMemoryMsg DB " Using Internal PC Speaker", 13 + DB "Error: Insufficient memory", 0 + +ReinitMsg DB "PC Speaker reinitialised", 0 + +DSPVersion DW 0 +Forced DB 0 +InInterrupt DB 0 + +BytesToMix DW 1000 +MixSpeed DW 22000 +MixConst DW 0 + +MixSegment DW 0 +DMASegment DW 0 + +MixTransferOffset DW 0 +MixTransferRemaining DW 0 + +DMASize DW 2048 + +OldIRQHandler DD 0 +TimerAccumulator DW 0 + +VolumeTable DB 256 Dup (0) + +; ÄÄ MixingRoutines ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixBufferPos DW 0 +OutputBufferPos DW 0 +OutputBlockEnd DW 1024 + +include mix.inc +include mono12b.mix + +MixFunctionTables Label + +include mono12b.inc ; contains the tables + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixConst ; Work out value.. and nearest + ; mixspeed value. Work out + ; volume translation table + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, CmdLineMixSpeed + Mov CX, MixSpeed + + Cmp AX, 12000 + JB GetMixConst1 + + Cmp AX, 44100 + JA GetMixConst1 + + Mov CX, AX + +GetMixConst1: + Mov DX, 0012h + Mov AX, 34DDh + + Div CX + ; AX = mix const + Mov MixConst, AX + + Mov DX, 12h + Mov AX, 34DDh + Div MixConst + + Mov MixSpeed, AX + + Mov CX, 256 + Mov DI, Offset VolumeTable + Push CS + Pop ES + + ; Volume table = (PosInTable / 256) * MixConst +GetMixConst2: + Mov AX, 256 + Sub AX, CX + Mul MixConst + Add AX, 80h + Mov AL, AH + Inc AL + StosB + + Loop GetMixConst2 + + Pop ES + Pop DS + PopA + Ret + +EndP GetMixConst + Assume DS:Nothing + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far + + Mov AX, 0FFFFh + Push CS + Pop DS + Assume DS:Driver + + Cmp AX, IRQ + JNE DetectCard1 + Cmp AX, Baseport + JNE DetectCard1 + Cmp AX, DMA + JNE DetectCard1 + + Mov EAX, 'Jeff' + + ClC + Ret + +DetectCard1: + StC + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc MixSamples ; Given DS:SI = info tables, CX = numchannels + + ; 1. Clean buffer + ; + update variables + ; 2. Update parameters + ; 3. Mix func + ; 4. Return + + Push CX + + Mov CX, BytesToMix + Mov ES, MixSegment + Mov DI, MIXTABLESIZE + Mov AX, 2020h + + Mov BX, CX ; BX = bytes to mix + Mov DX, CX + + Mov MixTransferOffset, DI ; } Memory write + Rep StosW ; } Memory write + Mov MixTransferRemaining, DX ; } + + Pop CX + +MixSamples2: + Test Byte Ptr [SI], 1 + JZ MixSamplesEnd2 + Cmp Byte Ptr [SI+36h], 100 + JE MixSamplesEnd2 + + Push CX + Mov CX, [SI] + + Test CH, 2 + JZ MixSamples3 + And Byte Ptr [SI], Not 1 + Jmp MixSamplesEnd + +MixSamples3: + Test CL, 20h ; New freq? + JZ MixSamples5 + + Mov AX, [SI+10h] + Mov DX, [SI+12h] + Mov BX, MixSpeed + Cmp DX, BX + JAE MixSamplesHandleError + + Div BX + ShL EAX, 16 + Xor AX, AX + Div BX + Mov STEPVALUE, EAX + +MixSamples4: + Test CH, 1 + JZ MixSamples5 + + Mov DWord Ptr [SI+1Ch], 0 ; Current Volume = 0 + ; for volume sliding. +MixSamples5: + Test CX, 8440h ; New volume or panning? + JZ MixSamplesMix + + Xor AX, AX + Test CH, 8 ; Muted? + JNZ MixModeCommon + +Mix0Mode: ; 16-bit mixing, no interpolation, no ramping +Mix0ModeMono: + Mov AL, [SI+20h] + ShR AL, 1 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AX, 30 ; Use left only-mixing for mono + +MixModeCommon: ; Requires AX = 30/60/90 etc. depending + ; On mixing mode type. + ; This will add 180 for 16-bit, + ; And sort out loop types. + Mov BL, [SI+0Ah] + Test Byte Ptr [SI+18h], 2 ; 16 bit? + JZ MixModeCommon1 + + Add AX, 60 + +MixModeCommon1: + Cmp BL, 8 + JB MixModeCommon3 ; No loop + JE MixModeCommon2 ; Forwards loop + + Add AX, 10 + +MixModeCommon2: + Add AX, 10 + +MixModeCommon3: + Add AX, Offset MixFunctionTables + Mov [SI+8], AX ; Offset... + + +MixSamplesMix: + Mov BX, [SI+8] ; BX = offset into + Mov EAX, [CS:BX+2] + Mov DWord Ptr PreMixFunction, EAX + Mov EAX, [CS:BX+6] + Mov DWord Ptr MixFunctionSeparateBackwards, EAX + + Mov AX, MixTransferRemaining + Mov MixBlockSize, AX + Mov MixBufferOffset, MIXTABLESIZE + + Mov EAX, CURRENTPOSITION + Mov OLDPOSITION, EAX + + Call Word Ptr [CS:BX] + + And Word Ptr [SI], 0111100010001101b + Jmp MixSamplesEnd + +MixSamplesHandleError: + Mov Word Ptr [SI], 200h + + Test Byte Ptr [SI+3Ah], 80h + JNZ MixSamplesEnd + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Turn off channel + +MixSamplesEnd: + Pop CX + +MixSamplesEnd2: + Add SI, 128 + Dec CX + JNZ MixSamples2 + + Ret + +EndP MixSamples + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PCSpeakerIRQHandler + + Push AX + Push BX + Push DS + + Mov DS, CS:DMASegment + Mov BX, CS:OutputBufferPos + + Mov AL, [BX] + Out 42h, AL + + Mov AX, CS + Mov DS, AX + Assume DS:Driver + + Inc BX + ; OK.. which IRQ handler? + Mov AX, MixConst + Add TimerAccumulator, AX + JC PCSpeakerIRQHandler1 + + Mov AL, 20h + Out 20h, AL + Jmp PCSpeakerIRQHandler2 + +PCSpeakerIRQHandler1: + PushF + Call OldIRQHandler + +PCSpeakerIRQHandler2: + Mov OutputBufferPos, BX + Cmp BX, OutputBlockEnd + JAE PCSpeakerIRQHandler3 + +PCSpeakerIRQHandlerEnd: + Pop DS + Pop BX + Pop AX + + IRet + +PCSpeakerIRQHandler3: + Mov BX, DMASize + Mov AX, OutputBlockEnd + Add AX, BX + Cmp AX, DMABUFFERLENGTH + JBE PCSpeakerIRQHandler4 + + Mov AX, BX + Mov OutputBufferPos, 0 + +PCSpeakerIRQHandler4: + Mov OutputBlockEnd, AX + + Cmp InInterrupt, 0 + JA PCSpeakerIRQHandlerEnd + + Inc InInterrupt + + ClD + + PushAD + Push ES + + Mov ES, CS:DMASegment + Mov DI, OutputBufferPos + + Call SaveEMSPageFrame + + StI + ; BX = bytes required + + Cmp MixTransferRemaining, 0 + JNE SBProIRQHandler4 + Assume DS:Nothing + +SBProIRQHandler3: + Push BX + Push ES + Push DI + + Call Update + Call MixSamples + + Pop DI + Pop ES + Pop BX + +SBProIRQHandler4: + Mov DS, MixSegment + Mov SI, MixTransferOffset + Mov DX, BX ; DX = samples to transfer + Cmp DX, MixTransferRemaining + JBE SBProIRQHandler5 + + Mov DX, MixTransferRemaining + +SBProIRQHandler5: + Push BX + Push DX + +SBProIRQHandler6: + Mov BX, [SI] + SAR BX, 6 + + Test BH, BH + JNZ SBProIRQHandlerClip1 + +SBProIRQHandler7: + Mov AL, [CS:VolumeTable+BX] + StosB ; } Memory write + + Add SI, 2 + Dec DX + JNZ SBProIRQHandler6 + + Pop DX + Pop BX + + Sub MixTransferRemaining, DX ; } Memory write + Sub BX, DX + JNZ SBProIRQHandler3 + + Mov MixTransferOffset, SI ; } Memory write + + Call RestoreEMSPageFrame + + Dec InInterrupt + +PCSpkEnd2: + Pop ES + PopAD + Pop DS + Pop BX + Pop AX + IRet + +SBProIRQHandlerClip1: + Mov BX, 0 + JS SBProIRQHandler7 + Mov BX, 0FFh + Jmp SBProIRQHandler7 + +EndP PCSpeakerIRQHandler + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + + PushAD + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Mov OutputBufferPos, 0 + Mov OutputBlockEnd, 1024 + + Mov AL, 34h ; Program IRQ 0. LSB&MSB, Rate gen + Out 43h, AL + + Mov AX, MixConst + Out 40h, AL + Mov AL, AH + Out 40h, AL + ; Program PC Speaker's IRQ + Mov AL, 90h + Out 43h, AL + + In AL, 61h + Or AL, 3 + Out 61h, AL ; Enable sound. + + Xor AX, AX + Mov ES, AX + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset PCSpeakerIRQHandler + + ClI + + XChg [ES:20h], EAX + Mov OldIRQHandler, EAX + + StI + + Pop ES + Pop DS + PopAD + + Ret + +EndP SetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIRQ + + PushAD + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Mov AL, 0B6h ; Reset PCSpeaker control + Out 43h, AL + + In AL, 61h ; Enable PC Speaker to be + And AL, 0FCh ; controlled by other programs + Out 61h, AL + + + Mov AL, 34h ; Reset IRQ calling rate. + Out 43h, AL + Xor AL, AL + Out 40h, AL + Out 40h, AL + + Xor AX, AX + Mov ES, AX + + Mov EAX, OldIRQHandler + Mov [ES:20h], EAX + + Pop ES + Pop DS + PopAD + + Ret + +EndP ResetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Call GetEMSPageFrame + Mov EMSPageFrame, AX + + Call GetMixConst + + Mov AX, 661 + Mul MixSpeed + Add AX, 0FFFFh + AdC DX, 2080 + + Mov BX, (DMABUFFERLENGTH)/16 + Add BX, DX + + ; Allocate MixSegment first + Mov AH, 48h + + Int 21h + JNC InitSound1 + +InitSoundNoMemory: + Mov SI, Offset SBProNoMemoryMsg + Ret + +InitSound1: + Mov MixSegment, AX + Add AX, DX + Mov DMASegment, AX + + Call GetTempo + Call SetTempo + Call SetIRQ + + Mov SI, Offset SBProMsg + + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Call ResetIRQ + Call SetIRQ + + Mov SI, Offset ReInitMsg + Mov BX, 40 + Call SetInfoLine + + Pop ES + Pop DS + PopA + + Ret + +EndP ReInitSound + Assume DS:Nothing + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Mov AX, MixSegment + Test AX, AX + JZ UnInitSound1 + + Mov ES, AX + Mov AH, 49h ; Release MixSegment + Int 21h + + Call ResetIRQ + +UnInitSound1: + Ret + +EndP UnInitSound + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + Ret + +EndP Poll + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Push AX + Push BX + Push DX + + Push BX + + Mov AX, MixSpeed + Mov BX, AX + Xor DX, DX + + ShL AX, 1 + RCL DX, 1 ; DX:AX = Mixspeed*2 + + ShR BX, 1 ; BX = Mixspeed/2 + + Add AX, BX + AdC DX, 0 ; DX:AX = Mixspeed*2.5 + + Pop BX ; BX = tempo + Div BX + + Mov BytesToMix, AX + + Pop DX + Pop BX + Pop AX + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + PushA + Push DS + + Mov BX, AX ; BX = MixVolume + + Mov AX, CS:MixSegment + Test AX, AX + JZ SetMixVolume2 + + Mov DS, AX + + Mov CX, MIXTABLESIZE/2 + Mov SI, MIXTABLESIZE-2; Starting point - working backwards + +SetMixVolume1: + Mov AX, CX + + Dec AX ; AH = volume, AL = wave value. + Xor DX, DX + XChg AH, DL ; DL = Volume, AX = wave value + CBW + + IMul DX ; DX:AX = Volume * Wave Value + ; Ranges -8192->8128 + + IMul BX ; DX:AX = Volume * Wave Value * Mixing Volume + ; Ranges -1048576->1040384 + + Add AX, 64 + AdC DX, 0 + + ShRD AX, DX, 7 + Mov [SI], AX + Sub SI, 2 + + Loop SetMixVolume1 + +SetMixVolume2: + Pop DS + PopA + + Ret + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc LoadSample Far + + StC + Ret + +EndP LoadSample + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + StC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far ; Returns AX, given DI + + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far ; Given AX, DI + + Ret + +EndP SetVariable + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. + +StopAfterPlay DW 0 +DefaultChannels DW 64 + DW 5 Dup (0) + + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/PNP.INC b/SoundDrivers/PNP.INC new file mode 100755 index 0000000..fecac2e --- /dev/null +++ b/SoundDrivers/PNP.INC @@ -0,0 +1,224 @@ +; +; Plug and play include file. Driver needs to define PNPVENDORID and +; PNPSERIALID which will be used to identify the card. +; +; Call function PnP_Detect +; + + +PnP_SerialID DD 0 +PnP_VendorID DD 0 +PnP_ReadPort DW 0 +PnP_CSN DB 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_Delay + + Push AX CX + + Mov CX, 180h +PnP_Delay1: + In AL, 21h + Loop PnP_Delay1 + + Pop CX AX + Ret + +EndP PnP_Delay + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_WriteData + + Mov DX, 279h + Out DX, AL + + Mov AL, AH + Mov DH, 0Ah + Out DX, AL + Ret + +EndP PnP_WriteData + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_ReadRegister + + Mov DX, 279h + Out DX, AL + + Mov DX, PnP_ReadPort + In AL, DX + + Ret + +EndP PnP_ReadRegister + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_Isolate + + Mov AX, 402h + Call Pnp_WriteData ; Reset CSNs + +PnP_IsolateNextCard: + Mov AX, 0003h + Call PnP_WriteData ; Wake[0] + + Mov AX, PnP_ReadPort + ShL AX, 6 + Xor AL, AL + Call PnP_WriteData ; Set Read Data port. + + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + + Mov AL, 1 ; Serial Isolation + Mov DX, 279h + Out DX, AL + + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + + Mov BL, 6Ah + Mov CX, 64 + Mov DX, PnP_ReadPort + + ClI + +PnP_Isolate1: + ShR PnP_SerialID, 1 + RCR PnP_VendorID, 1 + + Mov BH, BL + ShR BH, 1 + Xor BH, BL + ShR BX, 1 + + In AL, DX + Mov AH, AL + Call PnP_Delay + In AL, DX + Call PnP_Delay + + Cmp AX, 55AAh + JNE PnP_Isolate2 + + Xor BL, 80h + Or SerialNumber, 80000000h + +PnP_Isolate2: + Dec CX + JNZ PnP_Isolate1 + + Mov CX, 8 + Xor BH, BH + +PnP_Isolate3: + ShR BH, 1 + + In AL, DX + Mov AH, AL + Call PnP_Delay + In AL, DX + Call PnP_Delay + Cmp AX, 55AAh + JNE PnP_Isolate4 + + Or BH, 80h + +PnP_Isolate4: + Dec CX + JNZ PnP_Isolate3 + + Cmp BL, BH ; Matching Checksum? + JNE PnP_IsolateFinished + + ; assign CSN + Inc PnP_CSN + + Mov AL, 6 + MOv AH, PnP_CSN + Call PnP_WriteData + + Cmp PnP_VendorID, PNPVENDORID + JNE PnP_IsolateNextCard + Cmp PnP_SerialID, PNPSERIALID + JNE PnP_IsolateNextCard + + Mov AL, 60h + Call PnP_ReadData + Mov AH, AL + Mov AL, 61h + Call PnP_ReadData ; AX = address. + + Mov AL, 70h + Call PnP_ReadData ; AL[3:0] = IRQ + + Mov AL, 74 + Call PnP_ReadData ; AL[2:0] = DMA + + Jmp PnP_IsolateNextCard + +PnP_IsolateFinished: + Cmp PnP_CSN, 0 + JNE PnP_IsolateEnd + + StC + +PnP_IsolateEnd: + Ret + +EndP PnP_Isolate + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Pnp_Detect ; returns carry clear if succesful + + Xor AL, AL + Mov DX, 279h + Out DX, AL + Out DX, AL + + Mov AL, 6Ah ; Starting value + Mov CX, 32 + +PnP_InitiationKeyLoop: + Out DX, AL + + Mov AH, AL + ShR AH, 1 + Xor AH, AL + ShR AX, 1 + + Dec CX + JNZ PnP_InitiationKeyLoop + +; Try three ports before concluding no PnP cards: 20Fh, 27Bh, 213h + + Mov PnP_ReadPort, 20Fh + Call PnP_Isolate + JNC PnP_DetectEnd + + Mov PnP_ReadPort, 27Bh + Call PnP_Isolate + JNC PnP_DetectEnd + + Mov PnP_ReadPort, 213h + Call PnP_Isolate + +PnP_DetectEnd: ; Return PnP to wait for key state + Mov AX, 202h + Call PnP_WriteData + + Ret + +EndP PnP_Detect + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + diff --git a/SoundDrivers/Q.INC b/SoundDrivers/Q.INC new file mode 100755 index 0000000..c6e45a4 --- /dev/null +++ b/SoundDrivers/Q.INC @@ -0,0 +1,34 @@ + +QualityFactorTable Label DWord + DD 3F800000h, 3F7A8874h, 3F752ECBh, 3F6FF262h + DD 3F6AD298h, 3F65CED3h, 3F60E678h, 3F5C18F1h + DD 3F5765ACh, 3F52CC19h, 3F4E4BACh, 3F49E3DCh + DD 3F459421h, 3F415BF8h, 3F3D3AE1h, 3F39305Ch + DD 3F353BEFh, 3F315D21h, 3F2D937Ch, 3F29DE8Ch + DD 3F263DE0h, 3F22B109h, 3F1F379Ah, 3F1BD12Ah + DD 3F187D50h, 3F153BA8h, 3F120BCDh, 3F0EED5Fh + DD 3F0BDFFDh, 3F08E34Bh, 3F05F6EEh, 3F031A8Ch + DD 3F004DCEh, 3EFB20BEh, 3EF5C3D4h, 3EF0843Ch + DD 3EEB6156h, 3EE65A84h, 3EE16F2Dh, 3EDC9EBBh + DD 3ED7E89Bh, 3ED34C3Ch, 3ECEC913h, 3ECA5E95h + DD 3EC60C3Bh, 3EC1D181h, 3EBDADE7h, 3EB9A0EEh + DD 3EB5AA1Ah, 3EB1C8F2h, 3EADFCFFh, 3EAA45CEh + DD 3EA6A2EDh, 3EA313EEh, 3E9F9862h, 3E9C2FE1h + DD 3E98DA02h, 3E95965Fh, 3E926494h, 3E8F4440h + DD 3E8C3504h, 3E893681h, 3E86485Dh, 3E836A3Eh + DD 3E809BCCh, 3E7BB965h, 3E765939h, 3E711670h + DD 3E6BF06Ah, 3E66E68Ah, 3E61F836h, 3E5D24D6h + DD 3E586BD9h, 3E53CCADh, 3E4F46C5h, 3E4AD998h + DD 3E46849Eh, 3E424752h, 3E3E2134h, 3E3A11C4h + DD 3E361887h, 3E323503h, 3E2E66C2h, 3E2AAD4Fh + DD 3E270838h, 3E23770Fh, 3E1FF965h, 3E1C8ED2h + DD 3E1936ECh, 3E15F14Ch, 3E12BD91h, 3E0F9B56h + DD 3E0C8A3Eh, 3E0989E9h, 3E0699FDh, 3E03BA20h + DD 3E00E9F9h, 3DFC5268h, 3DF6EEF8h, 3DF1A8FCh + DD 3DEC7FD5h, 3DE772E5h, 3DE28191h, 3DDDAB43h + DD 3DD8EF67h, 3DD44D6Ch, 3DCFC4C4h, 3DCB54E6h + DD 3DC6FD4Ah, 3DC2BD6Ah, 3DBE94C7h, 3DBA82DFh + DD 3DB68738h, 3DB2A157h, 3DAED0C5h, 3DAB150Eh + DD 3DA76DC0h, 3DA3DA6Ch, 3DA05AA3h, 3D9CEDFCh + DD 3D99940Eh, 3D964C71h, 3D9316C3h, 3D8FF2A1h + DD 3D8CDFABh, 3D89DD84h, 3D86EBCFh, 3D840A32h diff --git a/SoundDrivers/REQPROC.INC b/SoundDrivers/REQPROC.INC new file mode 100755 index 0000000..0cdbebc --- /dev/null +++ b/SoundDrivers/REQPROC.INC @@ -0,0 +1,31 @@ + +ProcedureTableStart Label +Update DD 0 +GetSampleHeader DD 0 +GetSampleLocation DD 0 + DD 0 +GetEMSPageFrame DD 0 +SaveEMSPageFrame DD 0 +RestoreEMSPageFrame DD 0 +GetTempo DD 0 ; Gets tempo in BX +M_FunctionHandler DD 0 +SetInfoLine DD 0 +Music_LoadAllSamples DD 0 +GlobalKeyList DD 0 +IdleUpdateInfoLine DD 0 +DrawHeaderFunction DD 0 +FillHeaderFunction DD 0 +GotoHomeDirectory DD 0 +GetFileName DD 0 +SetDirectory DD 0 +StopPlayback DD 0 +GetEnvironment DD 0 +GetChannelTables DD 0 +RecalculateAllVolumes DD 0 +UARTBufferEmpty DD 0 +UARTSend DD 0 +S_GetDestination DD 0 +S_DrawString DD 0 + DD 32 - ($-ProcedureTableStart)/4 Dup (0) + + diff --git a/SoundDrivers/SAM9407.ASM b/SoundDrivers/SAM9407.ASM new file mode 100755 index 0000000..67bfa61 --- /dev/null +++ b/SoundDrivers/SAM9407.ASM @@ -0,0 +1,1008 @@ + + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;*********************************************** + +NUMMEMORYBLOCKS EQU 64 + +PNPSERIALID EQU 0FFFFFFFFh +PNPVENDORID EQU 80719304h + +MMT_MAXENTRIES EQU 64 +MMT_MAXSIZE EQU 3*MMT_MAXENTRIES + + +SAM_RD_MEM EQU 2h +SAM_GET_MMT EQU 3h +SAM_GEN_INT EQU 48h +SAM_GET_VOI EQU 51h +SAM_VOI_OPEN EQU 52h +SAM_VOI_CLOSE EQU 53h +SAM_VOI_START EQU 54h +SAM_VOI_STOP EQU 55h +SAM_VOI_VOL EQU 56h +SAM_VOI_MAIN EQU 57h +SAM_VOI_PITCH EQU 58h +SAM_VOI_AUX EQU 59h +SAM_VOI_FILT EQU 5Ah +SAM_VOI_MEM EQU 5Bh +SAM_GET_POS EQU 5Ch +SAM_ADD_POS EQU 5Dh + +SAM9407Message DB "Dream SAM9407 Detected", 13 + DB "Port ", 0FDh, "Xh, ", 0FDh, "Dk RAM", 0 + +StatusLine DB "FreeSAM ", 0FDh, "Dk", 0 + +SAMUpdateFlag DB 0 + +ALIGN 4 +OldIRQHandler DD 0 +SAMUpdateTimer DW 0 +SAMUpdateCount DW 0 + +MMTData DW MMT_MAXSIZE Dup (0) + +MemoryBlocks DD NUMMEMORYBLOCKS*2 Dup (0) + ; Memory blocks are offset/size pairs. + +SampleInformation DD 100*4 Dup (0) + ; Sample data is a struct + ; Offset 0: Starting address + ; Offset 4: Loop start + ; Offset 8: Loop end + ; Offset 0Ch: ?? + +SlaveChannelOffset DW 0 + +; ÄÄ EmptyFunction ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc EmptyFunction Far + + Xor AX, AX + StC + Ret + +EndP EmptyFunction + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SAM9407ReceiveByte ; Returns AL = data + ; BL = status + + Push DX + Mov DX, CS:BasePort + Inc DX + +SAM9407ReceiveByte1: + In AL, DX + Test AL, AL + JS SAM9407ReceiveByte1 + + Mov BL, AL + Dec DX + And BL, 30h + + In AL, DX + Pop DX + + Ret + +EndP SAM9407ReceiveByte + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SAM9407ReceiveWord ; Returns AX + + Call SAM9407ReceiveByte + Mov AL, AH + Call SAM9407ReceiveByte + XChg AL, AH + + Ret + +EndP SAM9407ReceiveWord + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SAM9407ReceiveDWord ; Returns EAX + + Call SAM9407ReceiveByte + RoR EAX, 8 + Call SAM9407ReceiveByte + RoR EAX, 8 + Call SAM9407ReceiveByte + RoR EAX, 8 + Call SAM9407ReceiveByte + RoR EAX, 8 + + Ret + +EndP SAM9407ReceiveDWord + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SAM9407SendControlByte ; BL = data + + Push AX + Push DX + + Mov DX, CS:BasePort + Inc DX + +SAM9407SendControlByte1: + In AL, DX + Test AL, 40h + JNZ SAM9407SendControlByte1 + + Mov AL, BL + Out DX, AL + + Pop DX + Pop AX + + Ret + +EndP SAM9407SendControlByte + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SAM9407SendDataByte ; AL = data + + Push DX + Push AX + + Mov DX, CS:BasePort + Inc DX + +SAM9407SendDataByte1: + In AL, DX + Test AL, 40h + JNZ SAM9407SendDataByte1 + + Pop AX + Dec DX + + Out DX, AL + + Pop DX + + Ret + +EndP SAM9407SendDataByte + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SAM9407SendDataWord ; AX = data + + Call SAM9407SendDataByte + Mov AL, AH + Call SAM9407SendDataByte + Ret + +EndP SAM9407SendDataWord + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SAM9407SendDataDWord ; EAX = data + + Call SAM9407SendDataByte + ShR EAX, 8 + Call SAM9407SendDataByte + ShR EAX, 8 + Call SAM9407SendDataByte + ShR AX, 8 + Call SAM9407SendDataByte + Ret + +EndP SAM9407SendDataDWord + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SAM9407ReceiveString ; ES:DI points to deposit point. + ; EAX = memory address + ; CX = count + + Mov BL, SAM_RD_MEM + Call SAM9407SendControlByte + Call SAM9407SendDataDWord + Mov AX, CX + Call SAM9407SendDataWord + +SAM9407InString1: + Call SAM9407ReceiveByte + Cmp AL, 0ABh + JE SAM9407InStringError + Cmp AL, 0ACh + JNE SAM9407InString1 + +SAM9407InString2: + Mov DX, CS:BasePort + Add DX, 2 + + Rep InsW + + DB 85h + +SAM9407InStringError: + StC + Ret + +EndP SAM9407ReceiveString + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetWaitforSend ; Given DX = control port + + Xor CX, CX + +ResetWaitforSend1: + In AL, DX + Test AL, 40h + LoopNZ ResetWaitforSend + Ret + +EndP ResetWaitforSend + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetWaitforReceive + + Xor CX, CX + +ResetWaitforReceive1: + In AL, DX + Test AL, 80h + JNZ ResetWaitforReceive2 + + Dec DX + In AL, DX + Inc DX + Cmp AL, 0FEh + JE ResetWaitforReceive3 + +ResetWaitforReceive2: + Loop ResetWaitforReceive1 + + StC + Ret + +ResetWaitforReceive3: + ClC + Ret + +EndP ResetWaitforReceive + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SAMSendChannelNumber + + Mov AX, SI + Sub AX, CS:SlaveChannelOffset + ShR AX, 7 + Call SAM9407SendDataByte + + Ret + +EndP SAMSendChannelNumber + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SAMOpenVoice + + Cmp Byte Ptr [SI+2], 1 + JE SAMOpenVoice1 ; Already opened! + + Mov Byte Ptr [SI+2], 1 + + Mov BL, [SI+36h] ; Sample number + Xor DH, DH + And BX, 0FFh + ShL BX, 4 + + Mov DL, [Byte Ptr CS:SampleInformation+BX+3] + Sub DL, [Byte Ptr CS:SampleInformation+BX+7] + ; Carry 0 if inbank + ; Carry 1 if crossbank + + SBB DL, DL ; DL = 0 inbank + ; DL = 0FFh crossbank + + ShL DL, 7 ; DL = 0 inbank + ; DL = 80h crossbank + + Mov BL, SAM_VOI_OPEN + Call SAM9407SendControlByte + + Mov AX, SI + Sub AX, CS:SlaveChannelOffset + ShR AX, 7 + Or AL, DL + Call SAM9407SendDataByte + +SAMOpenVoice1: + Ret + +EndP SAMOpenVoice + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SAMStopNote ; Closes the voice. + + Cmp Byte Ptr [SI+2], 1 + JNE SAMStopNote1 + + Mov Byte Ptr [SI+2], 0 + Mov BL, SAM_VOI_CLOSE + Call SAM9407SendControlByte + Call SAMSendChannelNumber + +SAMStopNote1: + Ret + + +EndP SAMStopNote + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SAMSetVolume + + Cmp Byte Ptr [SI+2], 1 + JNE SAMSetVolume1 + + Mov BL, SAM_VOI_VOL + Call SAM9407SendControlByte + Call SAMSendChannelNumber + Mov AL, [SI+20h] + Call SAM9407SendDataByte + +SAMSetVolume1: + Ret + +EndP SAMSetVolume + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SAMSetPan + + Cmp Byte Ptr [SI+2], 1 + JNE SAMSetPan1 + +Comment ~ + Mov BL, SAM_VOI_PAN + Call SAM9407SendControlByte + Call SAMSendChannelNumber + Mov AL, [SI+37h] + Call SAM9407SendDataByte +~ +SAMSetPan1: + Ret + +EndP SAMSetPan + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SAMSetPitch + +; Pitch value sent is 400h for nominal frequency of 37.5khz, linear scale +; -> Value sent = Frequency*400h / 37500 +; = Frequency * 0.02730666 +; = Frequency * 117281240 / 2^32 + + Cmp Byte Ptr [SI+2], 1 + JNE SAMSetPitch3 + + Mov EAX, 117281240 + Mul DWord Ptr [SI+10h] + + Cmp EDX, 0FFFFh + JA SAMSetPitch1 + + Mov BL, SAM_VOI_PITCH + Call SAM9407SendControlByte + Call SAMSendChannelNumber + Mov AX, DX + Call SAM9407SendDataWord + +SAMSetPitch3: + Ret + +SAMSetPitch1: + Call SAMStopNote + + Mov Word Ptr [SI], 200h + Test Byte Ptr [SI+3Ah], 80h + JNZ SAMSetPitch2 + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Signify channel off + +SAMSetPitch2: + Ret + +EndP SAMSetPitch + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SAMSetRegisters + +; First get offset of currently playing notes + +; Update Registers to play notes + +; Flow is as follows: +; If new note, open voice +; +; If pitch change, set pitch +; If volume change, set volume + filters +; +PlayNote: + + Ret + +EndP SAMSetRegisters + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SAMIRQHandler ; IRQ Handler has to + ; 1) Update GUS registers + ; 2) Update song position + Push AX + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, SAMUpdateTimer + Add SAMUpdateCount, AX + JC SAMIRQHandler1 + + Mov AL, 20h + Out 20h, AL + Jmp SAMIRQHandler2 + +SAMIRQHandler1: + PushF + Call [OldIRQHandler] + +SAMIRQHandler2: + Xor SAMUpdateFlag, 1 + JZ SAMIRQHandlerEnd + + PushAD + Push ES + + ClD + + Call SaveEMSPageFrame + Call Update ; Returns DS:SI, CX + Assume DS:Nothing + + Mov SlaveChannelOffset, SI + + Call SAMSetRegisters + Call RestoreEMSPageFrame + + Pop ES + PopAD + +SAMIRQHandlerEnd: + Pop DS + Pop AX + IRet + +EndP SAMIRQHandler + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetUART ; Given DX = Port + + Inc DX + + Mov AL, 0FFh ; Reset! + Out DX, AL + Out DX, AL ; Two resets required to ensure it'll work + + Call ResetWaitforReceive + JNC ResetUART1 + +ResetUARTError: + StC + Ret + +ResetUART1: ; Now to shove it into 'intelligent' mode. + Call ResetWaitforSend + JNZ ResetUARTError + + Mov AL, 3Fh ; Intelligent mode! + Out DX, AL + + Call ResetWaitforReceive + JC ResetUARTError + + Call ResetWaitforSend + JNZ ResetUARTError + + Mov AL, SAM_GEN_INT + Out DX, AL + + Call ResetWaitforSend + JNZ ResetUARTError + + Dec DX + Xor AL, AL + Out DX, AL + Inc DX + + Xor CX, CX + +ResetUART2: + In AL, DX + Test AL, 80h + JNZ ResetUART3 + + Mov AH, AL + Dec DX + In AL, DX + Inc DX + And AH, 30h + Cmp AX, 3088h + JE ResetUART4 + +ResetUART3: + Loop ResetUART2 + Jmp ResetUARTError + +ResetUART4: + Call ResetWaitforReceive + JC ResetUARTError + + Dec DX + + ClC + Ret + +EndP ResetUART + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far ; returns carry clear if succesful + + Push CS + Pop DS + +; Check whether the MPU can be reset + Mov DX, BasePort + Cmp DX, 0FFFFh + JE DetectCard1 + + Call ResetUART + JNC DetectCardFound + +DetectCardExit: + Ret + +DetectCard1: + Mov DX, 330h + Call ResetUART + JNC DetectCard2 + + Mov DX, 300h + Call ResetUART + JC DetectCardExit + +DetectCard2: + Mov BasePort, DX + +DetectCardFound: +; Find memory mapping table, + Mov BL, SAM_GET_MMT + Xor AL, AL + Call SAM9407SendControlByte + Call SAM9407SendDataByte + Call SAM9407ReceiveDWord + + Push CS + Pop ES + Mov CX, MMT_MAXSIZE + Mov DI, Offset MMTData + Call SAM9407ReceiveString + + Mov EAX, 'Jeff' + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov AL, 34h ; Program IRQ 0. LSB&MSB, Rate gen + Out 43h, AL + + Call GetTempo + Call SetTempo + Call ResetMemory + + Xor AX, AX + Mov ES, AX ; ES = 0 + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset SAMIRQHandler + + ClI + + XChg DWord Ptr [ES:20h], EAX ; Clock tick + Mov OldIRQHandler, EAX + + StI + + Mov SI, Offset SAM9407Message + Xor BX, BX + +Comment ~ + Mov BL, SAM_GET_VOI + Xor AL, AL + Call SAM9407SendControlByte + Call SAM9407SendDataByte + Call SAM9407ReceiveByte + Mov BL, AL +~ + Mov AX, BasePort + Mov EBX, DWord Ptr [MMTData+2] + ShR EBX, 9 + + ClC + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + Ret + +EndP ReInitSound + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Mov BL, 0FFh + Call SAM9407SendControlByte + + Mov AL, 34h + Out 43h, AL + + Xor AX, AX + Out 40h, AL + Out 40h, AL + + Mov ES, AX + Mov EAX, OldIRQHandler + Mov [ES:20h], EAX + + Ret + +EndP UnInitSound + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + Ret + +EndP Poll + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far ; BX = tempo... + + Push AX + Push BX + Push DX + + ; Frames per second = 2 * (0.4*Tempo) + Mov AX, 0C214h + Mov DX, 16h ; Ticks = (1193181/(2*0.4))/Tempo + Div BX + + ; AX contains counter. + Mov CS:SAMUpdateTimer, AX + + Out 40h, AL ; Timer IRQ. + Mov AL, AH + Out 40h, AL + + Pop DX + Pop BX + Pop AX + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + Ret + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load (0 based) +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc LoadSample Far + + StC + Ret + +EndP LoadSample + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release (1 based) +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + PushA + Push DS + Push ES + + Push CS + Pop DS + Push CS + Pop ES + + Mov SI, Offset MMTData+6 + Mov DI, Offset MemoryBlocks + +ResetMemory1: + Mov AX, [SI] + Add SI, 6 + + Cmp AX, -1 + JE ResetMemory2 + + Cmp AX, 1 + JNE ResetMemory1 + + Mov EAX, [SI-4] + StosD + Neg EAX + Add EAX, [SI+2] + StosD + Jmp ResetMemory1 + +ResetMemory2: + Mov CX, Offset MemoryBlocks+NUMMEMORYBLOCKS*2*4 + Sub CX, DI + Xor AX, AX + ShR CX, 1 + Rep StosW + + Pop ES + Pop DS + PopA + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + Push CS + Pop DS + Assume DS:Driver + + Mov SI, Offset MemoryBlocks+4 + Mov CX, NUMMEMORYBLOCKS + Xor EAX, EAX + +GetStatus1: + Add EAX, [SI] + Add SI, 8 + Loop GetStatus1 + + Mov SI, Offset StatusLine + ShR EAX, 9 + + ClC + Ret + +EndP GetStatus + Assume DS:Nothing + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Xor AX, AX + StC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far + + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far + + Ret + +EndP SetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 64 ; Maximum number of channels the + ; driver can handle. +StopAfterPlay DW 0 +DefaultChannels DW 64 + + DW 5 Dup (0) + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/SB16B.ASM b/SoundDrivers/SB16B.ASM new file mode 100755 index 0000000..d1855cb --- /dev/null +++ b/SoundDrivers/SB16B.ASM @@ -0,0 +1,2001 @@ + + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;********************************** + +STEREOENABLED EQU 1 +DMABUFFERLENGTH EQU 8192 +MIXRESOLUTION EQU 16 ; 16 bit mixing for the SB16 +MIXTABLESIZE EQU 2*256*65 + +SB16Msg DB "Sound Blaster 16 detected", 13 + DB "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, DMA ", 0FDh, "D", 0 + +SB16NoMemoryMsg DB "Sound Blaster 16 detected", 13 + DB "Error: Insufficient memory", 0 + +ReinitMsg DB "Sound Blaster 16 reinitialised", 0 + +DSPVersion DW 0 +DSPIRQValue DB 0 +DSPDMAValue DB 0 +Forced DB 0 +Stereo DB 0 + +BytesToMix DW 1000 +SBMixConst DB 0 + +MixSegment DW 0 +DMASegment DW 0 +MixSegmentLength DW 0 + +MixTransferOffset DW 0 +MixTransferRemaining DW 0 + +CONFIGURATIONOFFSET EQU $+128 +CONFIGSIZE EQU 8 +MixMode DW 0 +MixModeOffset DW 0 +Filter DW 0 +DMASize DW 2048 + +IMR DW 0 +OldIRQHandler DD 0 + +FilterValue DD 0 +FilterValue2 DD 0 + +MIDIPort DW 0 +MIDIBuffer DB 256 Dup (0) +MIDIBufferHead DB 0 +MIDIBufferTail DB 0 + +IRQData Label Word + DW 20h, 1111111111111110b ; IRQ 0 + DW 24h, 1111111111111101b ; IRQ 1 + DW 28h, 1111110111111011b ; IRQ 2 + DW 2Ch, 1111111111110111b ; IRQ 3 + DW 30h, 1111111111101111b ; IRQ 4 + DW 34h, 1111111111011111b ; IRQ 5 + DW 38h, 1111111110111111b ; IRQ 6 + DW 3Ch, 1111111101111111b ; IRQ 7 + DW 1C0h, 1111111011111011b ; IRQ 8 + DW 1C4h, 1111110111111011b ; IRQ 9 + DW 1C8h, 1111101111111011b ; IRQ 10 + DW 1CCh, 1111011111111011b ; IRQ 11 + DW 1D0h, 1110111111111011b ; IRQ 12 + DW 1D4h, 1101111111111011b ; IRQ 13 + DW 1D8h, 1011111111111011b ; IRQ 14 + DW 1DCh, 0111111111111011b ; IRQ 15 + + +;********************************** + +SB16ScreenList Label + DW 8 + DW Near Ptr IdleFunctionList + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr SB16HeaderLine + + DW Near Ptr VolumeText + DW Near Ptr VolumeBox1 + DW Near Ptr VolumeBox2 + + DW Near Ptr DriverText + + DW Near Ptr MasterVolumeLeft ; 8 + DW Near Ptr MasterVolumeRight ; 9 + DW Near Ptr TrebleVolumeLeft ; 10 + DW Near Ptr TrebleVolumeRight ; 11 + DW Near Ptr BassVolumeLeft ; 12 + DW Near Ptr BassVolumeRight ; 13 + + DW Near Ptr MixFrequencyText + + DW 0 + +SB16HeaderLine DW 10 + DB "Sound Blaster 16 Driver", 0 + +DriverText DW 1 + DB 31, 48 + DB 21h + DB "Sound Blaster 16 Driver 1.4 for Impulse Tracker", 0 + +VolumeText DW 1 + DB 2, 13 + DB 20h + DB "Master Volume Left", 13 + DB "Master Volume Right", 13 + DB 13 + DB 13 + DB "Treble Left", 13 + DB "Treble Right", 13 + DB "Bass Left", 13 + DB "Bass Right", 13 + DB 0 + +MixFrequencyText DW 1 + DB 2, 23 + DB 20h + DB "Playback Frequency: ", 0FDh, "DHz", 0 +MixSpeed DW 45454 + +VolumeBox1 DW 0 + DB 21, 12, 27, 15 + DB 25 + +VolumeBox2 DW 0 + DB 14, 16, 18, 21 + DB 25 + +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +IdleFunctionList DD 0 + DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +MasterVolumeLeft DW 9 + DB 22, 13 + DW 0, 31 + DW 9, 0 + DW 0FFFFh, 9, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +MasterVolumeRight DW 9 + DB 22, 14 + DW 0, 31 + DW 9, 1 + DW 8, 10, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +TrebleVolumeLeft DW 9 + DB 15, 17 + DW 0, 15 + DW 9, 2 + DW 9, 11, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +TrebleVolumeRight DW 9 + DB 15, 18 + DW 0, 15 + DW 9, 3 + DW 10, 12, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +BassVolumeLeft DW 9 + DB 15, 19 + DW 0, 15 + DW 9, 4 + DW 11, 13, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +BassVolumeRight DW 9 + DB 15, 20 + DW 0, 15 + DW 9, 5 + DW 12, 0FFFFh, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +VolumeTable DB 6 Dup (0) + +; ÄÄ MixingRoutines ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixBufferPos DW 0 + +include dma.inc +include mix.inc +include m12bit.mix + +MixFunctionTables Label + +include m12bit.inc ; contains the tables + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SBOut ; AL = data + ; DX = 2xCh + + Push AX + +SBOut1: + In AL, DX + Test AL, AL + JS SBOut1 + + Pop AX + Out DX, AL + + Ret + +EndP SBOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SBIn ; DX = 2xEh, returns AL + +SBIn1: + In AL, DX + Test AL, AL + JNS SBIn1 + + Add DL, 0Ah-0Eh ; DX = 2xAh -> Data read port + In AL, DX + Add DL, 0Eh-0Ah + + Ret + +EndP SBIn + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectUART ; Given DX = Port + +; From SB-DevKit + + ClI + + Inc DX + Xor CX, CX + +DetectUART1: + In AL, DX + Test AL, 40h ; Ready for output + LoopNZ DetectUART1 + JNZ DetectUARTError + + Mov AL, 0FFh ; Reset! + Out DX, AL + + Xor CX, CX +DetectUART2: + In AL, DX + Test AL, 80h + JNZ DetectUART3 + + Dec DX + In AL, DX + Inc DX + Cmp AL, 0FEh + JE DetectUART4 + +DetectUART3: + Loop DetectUART2 + +DetectUARTError: + StI + StC + Ret + +DetectUART4: ; Now to shove it into 'intelligent' mode. + Xor CX, CX + +DetectUART5: + In AL, DX + Test AL, 40h + LoopNZ DetectUART5 + JNZ DetectUARTError + + Mov AL, 3Fh ; Intelligent mode! + Out DX, AL + +DetectUART6: + Xor CX, CX +DetectUART7: + In AL, DX + Test AL, 80h + JNZ DetectUART8 + + Dec DX + In AL, DX + Inc DX + Cmp AL, 0FEh + JE DetectUART9 + +DetectUART8: + Loop DetectUART7 + + Jmp DetectUARTError + +DetectUART9: + StI + ClC + Ret + + +Comment ~ + + ClI + + Mov BH, 3 ; Try to init port twice. + +DetectUART1: + Mov BL, 64 ; 64 byte buffer + + Inc DX + Mov AL, 0FFh + Out DX, AL + + Mov AL, 3Fh + Out DX, AL + +DetectUART2: + Mov CX, 04000h + +DetectUART3: + In AL, DX + Test AL, 80h + LoopNZ DetectUART3 + JZ DetectUART4 + + Dec BH + JNZ DetectUART1 + + StI + StC + Ret + +DetectUART4: + Dec DX + In AL, DX + Inc DX + + Cmp AL, 0FEh ; UART acknowledge. + JE DetectUART5 + + Dec BL + JNZ DetectUART2 + + Dec BH + JNZ DetectUART1 + +DetectUART6: + StC + +DetectUART5: + StI + Ret + + ~ + +EndP DetectUART + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReinitUART + + Mov DX, MIDIPort + Test DX, DX + JZ ReinitUART1 + + Call DetectUART + +ReinitUART1: + Ret + +EndP ReinitUART + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetUART + + Mov DX, MIDIPort + Test DX, DX + JZ ResetUART1 + + Inc DX + Mov AL, 0FFh + Out DX, AL + +ResetUART1: + Ret + +EndP ResetUART + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SBGetRegister + + Out DX, AL + Inc DX + In AL, DX + Dec DX + + Ret + +EndP SBGetRegister + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetSBMixConst ; Work out value.. and nearest + ; mixspeed value. + + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, CmdLineMixSpeed + Mov CX, MixSpeed + Test AX, AX + JZ GetSBMixConst1 + + Mov CX, 45454 + Cmp AX, CX + JA GetSBMixConst1 + + Mov CX, 12000 + Cmp AX, CX + JB GetSBMixConst1 + + Mov CX, AX + +GetSBMixConst1: + Mov AX, 1000 + Mul AX + Div CX + Mov AH, AL + Neg AH + Mov SBMixConst, AH + + MovZX BX, AL + Mov AX, 1000 + Mul AX + Div BX + Mov MixSpeed, AX + + Pop DS + PopA + Ret + +EndP GetSBMixConst + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetDSP Far ; AX = Port + + Push AX + Push CX + Push DX + + Mov DX, AX + Add DL, 6 + Mov AL, 1 + Out DX, AL + + In AL, DX + In AL, DX + In AL, DX + In AL, DX + + Xor AL, AL + Out DX, AL + + Add DL, 8 + Mov CX, 200 + +ResetDSP1: + In AL, DX + Test AL, AL + JS ResetDSP2 + Loop ResetDSP1 + Jmp ResetDSP3 + +ResetDSP2: + Sub DL, 4 + In AL, DX + Cmp AL, 0AAh + JE ResetDSP4 + Add DL, 4 + Loop ResetDSP1 + +ResetDSP3: + StC + +ResetDSP4: + Pop DX + Pop CX + Pop AX + Ret + +EndP ResetDSP + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetDSPIRQ + + Mov DX, CS:BasePort + Add DL, 4 + Mov AH, CS:DSPIRQValue + Mov AL, 80h + Out DX, AX + + Ret + +EndP ResetDSPIRQ + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetDSPDMA + + Mov DX, CS:BasePort + Add DL, 4 + Mov AH, CS:DSPDMAValue + Mov AL, 81h + Out DX, AX + + Ret + +EndP ResetDSPDMA + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far + + Push CS + Pop DS + Assume DS:Driver + + Mov Forced, AL + + Mov AX, BasePort + Cmp AX, 0FFFFh + JE DetectCard1 + + Cmp AX, 210h + JB DetectCard9 + Cmp AX, 280h + JA DetectCard9 + + Call ResetDSP + JNC DetectCard2 + + Ret + +DetectCard1: + Mov AX, 210h + +DetectCard2: + Call ResetDSP + JNC DetectCard3 + Add AL, 10h + Cmp AL, 80h + JBE DetectCard2 + +DetectCard9: + StC + Ret + +DetectCard3: ; OK... DSP found. + ; Get DSP version + Mov BasePort, AX + + Mov DX, AX + Add DL, 0Ch ; 2xCh -> Data ready to send... + +DetectCardOuputLoop1: + In AL, DX + Test AL, AL + JS DetectCardOuputLoop1 + + Mov AL, 0E1h ; Get DSP version command + Out DX, AL + + Add DL, 0Eh-0Ch ; DX = 2xEh -> Data available status + + Call SBIn + Mov AH, AL ; AH = Major version number + Call SBIn ; AL = Minor version number + + Cmp AH, 4 ; SB DSP = 4.00+ + JAE DetectCard5 + +DetectCard4: + StC + Ret + +DetectCard5: + Mov DSPVersion, AX + + Add DL, 04h-0Eh ; 2x4h = Mixer index port + Mov AL, 80h ; IRQ select + Out DX, AL + Inc DL ; 2x5h = Mixer data port + + In AL, DX + + Dec DL + + Mov DSPIRQValue, AL + ; OK.. now get IRQ, or set IRQ + Mov BX, IRQ + Cmp BX, 0FFFFh + JE DetectCardIRQ1 + Cmp Forced, 0 + JE DetectCardIRQ1 + + Mov AH, 11h + Cmp BL, 2 + JE SetCardIRQ1 + Cmp BL, 9 + JE SetCardIRQ1 + + Mov AH, 12h + Cmp BL, 5 + JE SetCardIRQ1 + + Mov AH, 14h + Cmp BL, 7 + JE SetCardIRQ1 + + Mov AH, 18h + Cmp BL, 10 + JE SetCardIRQ1 + + StC + Ret + +SetCardIRQ1: + Mov AL, 80h + Out DX, AL + Inc DL + Mov AL, AH + Out DX, AL + Dec DL + Jmp DetectCard6 + +DetectCardIRQ1: + Mov BX, 2 + Test AL, 1 + JNZ DetectCardIRQ2 + + Mov BL, 5 + Test AL, 2 + JNZ DetectCardIRQ2 + + Mov BL, 7 + Test AL, 4 + JNZ DetectCardIRQ2 + + Mov BL, 10 + Test AL, 8 + JNZ DetectCardIRQ2 + + StC + Ret + +DetectCardIRQ2: + Cmp IRQ, 0FFFFh + JE DetectCardIRQ3 + + Cmp BX, IRQ + JE DetectCard6 + + StC + Ret + +DetectCardIRQ3: + Mov IRQ, BX + +DetectCard6: ; Detect DMA + Mov AL, 81h ; DMA select + Out DX, AL + Inc DL + In AL, DX ; AL = DMA + Dec DL + + Mov DSPDMAValue, AL + + Mov BX, DMA + Cmp BX, 0FFFFh + JE DetectCardDMA1 + Cmp Forced, 0 + JE DetectCardDMA1 + + Mov CL, 1 + Cmp BX, 1 + JB SetCardDMA1 + + Mov CL, 2 + JE SetCardDMA1 + + Cmp BX, 3 + JB DetectCard7 + + Mov CL, 8 + JE DetectCard7 + + Mov CL, 20h + Cmp BX, 5 + JB DetectCard7 + JE SetCardDMA1 + + Mov CL, 80h + Cmp BX, 7 + JA DetectCard7 + JE SetCardDMA1 + + Mov CL, 40h + +SetCardDMA1: + And AL, 0Bh + Test CL, 0Bh + JZ SetCardDMA4 + + Xor AL, AL + +SetCardDMA4: + Or CL, AL + + Mov AL, 81h + Out DX, AL + Inc DL + Mov AL, CL + Out DX, AL + Jmp DetectCard7 + +DetectCardDMA1: + Mov BX, 5 + Test AL, 20h + JNZ DetectCardDMA2 + + Inc BL + Test AL, 40h + JNZ DetectCardDMA2 + + Inc BL + Test AL, 80h + JNZ DetectCardDMA2 + + Mov BL, 0 + Test AL, 1 + JNZ DetectCardDMA2 + + Inc BL + Test AL, 2 + JNZ DetectCardDMA2 + + Add BL, 2 + Test AL, 8 + JNZ DetectCardDMA2 + +DetectCard8: + Call ResetDSPIRQ + StC + Ret + +DetectCardDMA2: + Cmp DMA, 0FFFFh + JE DetectCardDMA3 + + Cmp BX, DMA + JNE DetectCard8 + +DetectCardDMA3: + Mov DMA, BX + +DetectCard7: + Mov EAX, 'Jeff' + + ClC + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc MixSamples ; Given DS:SI = info tables, CX = numchannels + + ; 1. Clean buffer + ; + update variables + ; 2. Update parameters + ; 3. Mix func + ; 4. Return + + Push CX + + Mov CX, BytesToMix + Mov ES, MixSegment + Mov DI, MIXTABLESIZE + Xor EAX, EAX + Mov DX, CX + + Mov MixTransferOffset, DI ; } Memory write + + Cmp Stereo, 0 + JE MixSamples1 + + Add DX, DX + +MixSamples1: + Rep StosD ; } Memory write + +MixSamplesCont: + Mov MixTransferRemaining, DX ; } + + Pop CX + +MixSamples2: + Test Byte Ptr [SI], 1 + JZ MixSamplesEnd2 + Cmp Byte Ptr [SI+36h], 100 + JE MixSamplesEnd2 + + Push CX + Mov CX, [SI] + + Test CH, 2 + JZ MixSamples3 + And Byte Ptr [SI], Not 1 + + Jmp MixSamplesEnd + +MixSamples3: + Test CL, 20h ; New freq? + JZ MixSamples5 + + Mov AX, [SI+10h] + Mov DX, [SI+12h] + Mov BX, MixSpeed + Cmp DX, BX + JAE MixSamplesHandleError + + Div BX + ShL EAX, 16 + Xor AX, AX + Div BX + Mov STEPVALUE, EAX + +MixSamples4: + Test CH, 1 + JZ MixSamples5 + + Mov DWord Ptr [SI+1Ch], 0 ; Current Volume = 0 + ; for volume sliding. +MixSamples5: + Test CX, 8440h ; New volume or panning? + JZ MixSamplesMix + + Xor AX, AX + Test CH, 8 ; Muted? + JNZ MixModeCommon + + Cmp Stereo, 0 + JNE Mix0ModeStereo + +Mix0Mode: ; 16-bit mixing, no interpolation +Mix0ModeMono: ; and 16-bit mixing, interpolation + Mov AL, [SI+20h] + ShR AL, 1 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 30 ; Use left only-mixing for mono + Jmp MixModeCommon + +Mix0ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix0ModeSurround + + Mul Byte Ptr [SI+20h] ; Final volume + Add AX, 64 + ShR AX, 7 + Mov [SI+0Ch], AX ; Store into right volume + + Mov AL, 64 + Sub AL, [SI+37h] + Mul Byte Ptr [SI+20h] + Add AX, 64 + ShR AX, 7 + Mov [SI+0Eh], AX ; Left volume + + Mov CH, AL ; CH = left volume + Mov CL, [SI+0Ch] ; CL = right volume + Mov AX, 0 + + Test CX, CX + JZ MixModeCommon + + Mov AL, 30 ; Left only... + Test CL, CL + JZ MixModeCommon + + Mov AL, 60 + Test CH, CH + JZ MixModeCommon + + Mov AL, 90 + Cmp CL, CH + JZ MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix0ModeSurround: + Mov AL, [SI+20h] + ShR AL, 2 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 150 ; Surround + Jmp MixModeCommon + +MixModeCommon: ; Requires AX = 30/60/90 etc. depending + ; On mixing mode type. + ; This will add 180 for 16-bit, + ; And sort out loop types. + Mov BL, [SI+0Ah] + Test Byte Ptr [SI+18h], 2 ; 16 bit? + JZ MixModeCommon1 + + Add AX, 180 + +MixModeCommon1: + Cmp BL, 8 + JB MixModeCommon3 ; No loop + JE MixModeCommon2 ; Forwards loop + + Add AX, 10 + +MixModeCommon2: + Add AX, 10 + +MixModeCommon3: + Add AX, Offset MixFunctionTables + Add AX, MixModeOffset + Mov [SI+8], AX ; Offset... + +MixSamplesMix: + Mov BX, [SI+8] ; BX = offset into + Mov EAX, [CS:BX+2] + Mov DWord Ptr PreMixFunction, EAX + Mov EAX, [CS:BX+6] + Mov DWord Ptr MixFunctionSeparateBackwards, EAX + + Mov AX, BytesToMix + Mov MixBlockSize, AX + Mov MixBufferOffset, MIXTABLESIZE + + Mov EAX, CURRENTPOSITION + Mov OLDPOSITION, EAX + + Call Word Ptr [CS:BX] + + And Word Ptr [SI], 0111100010001101b + Jmp MixSamplesEnd + +MixSamplesHandleError: + Mov Word Ptr [SI], 200h + + Test Byte Ptr [SI+3Ah], 80h + JNZ MixSamplesEnd + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Turn off channel + +MixSamplesEnd: + Pop CX + +MixSamplesEnd2: + Add SI, 128 + Dec CX + JNZ MixSamples2 + + Ret + +EndP MixSamples + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc AckIRQ + Assume DS:Driver + + Mov AL, 20h + Cmp IRQ, 7 + JBE AckIRQ1 + + Out 0A0h, AL + +AckIRQ1: + Out 20h, AL + Ret + +EndP AckIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc CheckMIDI + + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Xor BX, BX + Mov DX, MIDIPort + + Mov BL, [MIDIBufferTail] + Test DX, DX + JZ CheckMIDIEnd + + Inc DX + Mov CX, 0FFFFh + +CheckMIDIAgain: + In AL, DX + + Test AL, 80h + LoopNZ CheckMIDIAgain + + Dec DX + In AL, DX + + Cmp AL, 0F0h + JAE CheckMIDIEnd + + Inc BL + Cmp BL, MIDIBufferHead + JE CheckMIDIEnd + + Mov [MIDIBuffer+BX], AL + Mov [MIDIBufferTail], BL +; Jmp CheckMIDIAgain + +CheckMIDIEnd: + Pop DS + Ret + +EndP CheckMIDI + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SB16IRQHandler + + PushAD + Push DS + Push ES + + CLD + + Mov AX, CS + Mov DS, AX + Assume DS:Driver + + Mov DX, BasePort + Add DL, 4 ; Mixer Port + Mov AL, 82h + Out DX, AL + Inc DL ; DX = BasePort+5 + In AL, DX + + Comment ~ + + Test AL, 1 + JZ SB8BitDigitalInterruptEnd + +SB8BitDigitalInterrupt: + Push AX + Add DL, 0Eh-5 + In AL, DX + Pop AX + +SB8BitDigitalInterruptEnd: + + ~ + + Test AL, 4 + JZ SBMIDIInterruptEnd + + Push AX + Call CheckMIDI + Pop AX + +SBMIDIInterruptEnd: + Test AL, 2 + JNZ SBDigitalInterrupt + + Call AckIRQ + Jmp SBIRQEnd + +SBDigitalInterrupt: + Mov DX, BasePort + Add DL, 0Fh + In AL, DX ; 16-bit IRQ ack. + + Call AckIRQ + + Mov AX, MixBufferPos + Mov BX, AX + Mul DMASize + Cmp AX, DMABUFFERLENGTH + JB SB16IRQHandler2 + + Xor AX, AX + Xor BX, BX + +SB16IRQHandler2: + Inc BX + Mov MixBufferPos, BX + + + ; OK... time to get next block + ; Check whether stereo thing is on.. + ; + LES DI, [ActualDMAPtr] + Add DI, AX + + Mov BX, DMASize ; BX = bytes required + ShR BX, 1 + ; BX = samples required + Mov BP, 4 ; Skip for mono + Mov CL, 2 ; Shift for mono + + Cmp Stereo, 0 + JE SB16IRQHandlerMono + + ShR BP, 1 + Inc CL + +SB16IRQHandlerMono: + Call SaveEMSPageFrame + + Cmp MixTransferRemaining, 0 + JNE SB16IRQHandler4 + Assume DS:Nothing + +SB16IRQHandler3: + Push BX + Push CX + Push BP + Push ES + Push DI + + Call Update + Call MixSamples + + Pop DI + Pop ES + Pop BP + Pop CX + Pop BX + +SB16IRQHandler4: + Mov DS, MixSegment + Mov SI, MixTransferOffset + Mov DX, BX ; DX = samples to transfer + Cmp DX, MixTransferRemaining + JBE SB16IRQHandler5 + + Mov DX, MixTransferRemaining + +SB16IRQHandler5: + Push DX + +SB16IRQHandler6: + MovSX EAX, Word Ptr [SI] + SAL EAX, CL + + Cmp EAX, -8000h + JL SB16IRQHandlerClip1 + Cmp EAX, 7FFFh + JG SB16IRQHandlerClip2 + +SB16IRQHandler7: + StosW ; } Memory write + + Add SI, BP + Dec DX + JNZ SB16IRQHandler6 + +SB16MixTransferEnd: + Pop DX + + Sub MixTransferRemaining, DX ; } Memory write + Sub BX, DX + JNZ SB16IRQHandler3 + + Mov MixTransferOffset, SI ; } Memory write + + Call RestoreEMSPageFrame + +SBIRQEnd: + + Pop ES + Pop DS + PopAD + IRet + +SB16IRQHandlerClip1: + Mov AX, 8000h + Jmp SB16IRQHandler7 + +SB16IRQHandlerClip2: + Mov AX, 7FFFh + Jmp SB16IRQHandler7 + +EndP SB16IRQHandler + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + + PushAD + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Add DI, Offset IRQData + Mov BX, [DI] + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset SB16IRQHandler + + XChg [ES:BX], EAX + Mov OldIRQHandler, EAX + + Mov AX, IMR + And AX, [DI+2] + + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Pop ES + Pop DS + PopAD + + Ret + +EndP SetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIRQ + + PushAD + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Mov BX, [IRQData+DI] + + Mov EAX, OldIRQHandler + Mov [ES:BX], EAX + + Pop ES + Pop DS + PopAD + + Ret + +EndP ResetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StartSB16 ; + + PushA + Push ES + + ; Setup DMA + Mov BX, DMASegment + Xor AX, AX + Mov DX, DMA + Mov DI, DMABUFFERLENGTH + Call SetDMA + + LES DI, ActualDMAPtr + Xor AX, AX + Mov CX, DMABUFFERLENGTH/2 + Rep StosW + + Mov MixBufferPos, 0 + Mov MixTransferRemaining, 0 + + Mov DX, BasePort + Add DL, 0Ch + + Mov AL, 0D1h ; turn on speaker + Call SBOut + + Mov AL, 40h ; time constant + Call SBOut + Mov AL, SBMixConst + Call SBOut + + Mov AL, 0B6h ; 16 bit, DAC + Call SBOut + Mov AL, Stereo + ShL AL, 5 + Or AL, 10h + Call SBOut + + Mov AX, DMASize + ShR AX, 1 + Dec AX + + Call SBOut ; DMALength, Lo + Mov AL, AH + Call SBOut + + Pop ES + PopA + + Ret + + Assume DS:Nothing + +EndP StartSB16 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixerRegisters + + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Pop DS + + Ret + +EndP GetMixerRegisters + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Call GetEMSPageFrame + Mov EMSPageFrame, AX + + In AL, 0A1h + Mov AH, AL + In AL, 21h + Mov IMR, AX + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + Mov DX, BasePort + Add DL, 4 + + Mov AL, 30h + Call SBGetRegister + ShR AL, 3 + Mov VolumeTable, AL + + Mov AL, 31h + Call SBGetRegister + ShR AL, 3 + Mov [VolumeTable+1], AL + + Mov AL, 44h + Call SBGetRegister + ShR AL, 4 + Mov [VolumeTable+2], AL + + Mov AL, 45h + Call SBGetRegister + ShR AL, 4 + Mov [VolumeTable+3], AL + + Mov AL, 46h + Call SBGetRegister + ShR AL, 4 + Mov [VolumeTable+4], AL + + Mov AL, 47h + Call SBGetRegister + ShR AL, 4 + Mov [VolumeTable+5], AL + + Call GetSBMixConst + + ; Parags to allocate = (4/(.4*31*16))*MixSpeed + 2080 + ; = .02016129*MixSpeed = (65536*.04032258*MixSpeed) / 65536 + + Mov AX, 1322 + Mul MixSpeed + Add AX, 0FFFFh + AdC DX, 2080 + + Mov BX, (DMABUFFERLENGTH*2)/16 + Add BX, DX + + ; Allocate MixSegment first + Mov AH, 48h + + Int 21h + JNC InitSound1 + +InitSoundNoMemory: + Mov SI, Offset SB16NoMemoryMsg + Ret + +InitSound1: + Mov MixSegment, AX + Add AX, DX + Mov DMASegment, AX + Sub DX, 2080 + Mov MixSegmentLength, DX + + Call SetIRQ + Call GetTempo + Call SetTempo + + Mov DX, 330h + Call DetectUART + JC DetectMIDI1 + + Mov MIDIPort, 330h + Jmp DetectMIDIEnd + +DetectMIDI1: + Mov DX, 300h + Call DetectUART + JC DetectMIDIEnd + + Mov MIDIPort, 300h + +DetectMIDIEnd: + + Mov SI, Offset SB16Msg + + Mov AX, BasePort + Mov BX, IRQ + Mov CX, DMA + + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, BasePort + Mov DX, AX + Call ResetDSP + + Call ResetUART + Call ResetIRQ + ; Delay.. + Mov DX, BasePort + Add DL, 0Ch + + Mov CX, 1000 +ReInitSound1: + In AL, DX + Loop ReInitSound1 + + Call SetIRQ + Call ReinitUART + + Mov SI, Offset ReInitMsg + Mov BX, 40 + Call SetInfoLine + + Mov AL, Stereo + Call SetStereo + + Pop ES + Pop DS + PopA + + Ret + +EndP ReInitSound + Assume DS:Nothing + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Mov DX, CS:BasePort + Add DL, 0Ch + + Mov AL, 0D3h + Call SBOut + + Mov AL, 0D5h + Call SBOut + + Mov AL, 0D9h + Call SBOut + + Mov AL, 0D5h + Call SBOut + + Call ResetUART + + Mov AX, BasePort + Call ResetDSP + + Call ResetDSPDMA + Call ResetDSPIRQ + + Mov AX, IMR + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Mov AX, MixSegment + Test AX, AX + JZ UnInitSound1 + + Mov ES, AX + Mov AH, 49h ; Release MixSegment + Int 21h + + Call ResetIRQ + +UnInitSound1: + Ret + +EndP UnInitSound + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + Push CS + Pop DS + Assume DS:Driver + +Poll1: + Call [UARTBufferEmpty] + JNC PollEnd + + Xor BX, BX + + ClI + + Mov BL, MIDIBufferHead + Cmp BL, MIDIBufferTail + JZ PollEnd ; Nothing in queue + + Inc BL + Mov AL, [MIDIBuffer+BX] + Mov MIDIBufferHead, BL + + Call [UARTSend] + Jmp Poll1 + +PollEnd: + StI + Ret + +EndP Poll + Assume DS:Nothing + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Push AX + Push BX + Push DX + + Push BX + + Mov AX, MixSpeed + Mov BX, AX + Xor DX, DX + + ShL AX, 1 + RCL DX, 1 ; DX:AX = Mixspeed*2 + + ShR BX, 1 ; BX = Mixspeed/2 + + Add AX, BX + AdC DX, 0 ; DX:AX = Mixspeed*2.5 + + Pop BX ; BX = tempo + Div BX + + Mov BytesToMix, AX + + Pop DX + Pop BX + Pop AX + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + PushA + Push DS + + Mov BX, AX ; BX = MixVolume + + Mov AX, CS:MixSegment + Test AX, AX + JZ SetMixVolume2 + + Mov DS, AX + + Mov CX, MIXTABLESIZE/2 + Mov SI, MIXTABLESIZE-2; Starting point - working backwards + +SetMixVolume1: + Mov AX, CX + + Dec AX ; AH = volume, AL = wave value. + Xor DX, DX + XChg AH, DL ; DL = Volume, AX = wave value + CBW + + IMul DX ; DX:AX = Volume * Wave Value + ; Ranges -8192->8128 + + IMul BX ; DX:AX = Volume * Wave Value * Mixing Volume + ; Ranges -1048576->1040384 + + Add AX, 64 + AdC DX, 0 + + ShRD AX, DX, 7 + Mov [SI], AX + Sub SI, 2 + + Dec CX + JNZ SetMixVolume1 + +SetMixVolume2: + Pop DS + PopA + + Ret + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Cmp CS:MixSegment, 0 + JE SetStereo1 + + Mov CS:Stereo, AL + Mov AX, CS:BasePort + Call ResetDSP + + Mov ES, CS:MixSegment + Mov CX, CS:MixSegmentLength + Mov DI, MIXTABLESIZE + ShL CX, 2 + Xor EAX, EAX + Rep StosD + + Call StartSB16 + +SetStereo1: + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include loadsam.inc + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset SB16ScreenList + + ClC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far ; Returns AX, given DI + + Xor AH, AH + Mov AL, [CS:VolumeTable+DI] + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far ; Given AX, DI + + Push DS + Push DX + + Push CS + Pop DS + Assume DS:Driver + + Mov [VolumeTable+DI], AL + + Mov DX, BasePort + Add DL, 4 + Mov AL, 30h + Mov AH, [VolumeTable] + ShL AH, 3 + Out DX, AX + + Mov AL, 31h + Mov AH, [VolumeTable+1] + ShL AH, 3 + Out DX, AX + + Mov AL, 44h + Mov AH, [VolumeTable+2] + ShL AH, 4 + Out DX, AX + + Mov AL, 45h + Mov AH, [VolumeTable+3] + ShL AH, 4 + Out DX, AX + + Mov AL, 46h + Mov AH, [VolumeTable+4] + ShL AH, 4 + Out DX, AX + + Mov AL, 47h + Mov AH, [VolumeTable+5] + ShL AH, 4 + Out DX, AX + + Pop DX + Pop DS + Ret + +EndP SetVariable + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. + +StopAfterPlay DW 0 +DefaultChannels DW 64 + DW 5 Dup (0) + + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/SB16C.ASM b/SoundDrivers/SB16C.ASM new file mode 100755 index 0000000..fe951d9 --- /dev/null +++ b/SoundDrivers/SB16C.ASM @@ -0,0 +1,1695 @@ + + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;********************************** + +STEREOENABLED EQU 1 +DMABUFFERLENGTH EQU 8192 +MIXRESOLUTION EQU 16 ; 16 bit mixing for the SB16 +MIXTABLESIZE EQU 2*256*65 + +SB16Msg DB "Sound Blaster 16 detected", 13 + DB "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, DMA ", 0FDh, "D", 0 + +SB16NoMemoryMsg DB "Sound Blaster 16 detected", 13 + DB "Error: Insufficient memory", 0 + +ReinitMsg DB "Sound Blaster 16 reinitialised", 0 + +DSPVersion DW 0 +DSPIRQValue DB 0 +DSPDMAValue DB 0 +Forced DB 0 +Stereo DB 0 + +BytesToMix DW 1000 +SBMixConst DB 0 + +MixSegment DW 0 +DMASegment DW 0 +MixSegmentLength DW 0 + +MixTransferOffset DW 0 +MixTransferRemaining DW 0 + +DMASize DW 2048 + +IMR DW 0 +OldIRQHandler DD 0 + +FilterValue DD 0 +FilterValue2 DD 0 + +IRQData Label Word + DW 20h, 1111111111111110b ; IRQ 0 + DW 24h, 1111111111111101b ; IRQ 1 + DW 28h, 1111110111111011b ; IRQ 2 + DW 2Ch, 1111111111110111b ; IRQ 3 + DW 30h, 1111111111101111b ; IRQ 4 + DW 34h, 1111111111011111b ; IRQ 5 + DW 38h, 1111111110111111b ; IRQ 6 + DW 3Ch, 1111111101111111b ; IRQ 7 + DW 1C0h, 1111111011111011b ; IRQ 8 + DW 1C4h, 1111110111111011b ; IRQ 9 + DW 1C8h, 1111101111111011b ; IRQ 10 + DW 1CCh, 1111011111111011b ; IRQ 11 + DW 1D0h, 1110111111111011b ; IRQ 12 + DW 1D4h, 1101111111111011b ; IRQ 13 + DW 1D8h, 1011111111111011b ; IRQ 14 + DW 1DCh, 0111111111111011b ; IRQ 15 + + +;********************************** + +SB16ScreenList Label + DW 8 + DW Near Ptr IdleFunctionList + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr SB16HeaderLine + + DW Near Ptr VolumeText + DW Near Ptr VolumeBox1 + DW Near Ptr VolumeBox2 + + DW Near Ptr DriverText + + DW Near Ptr MasterVolumeLeft ; 8 + DW Near Ptr MasterVolumeRight ; 9 + DW Near Ptr TrebleVolumeLeft ; 10 + DW Near Ptr TrebleVolumeRight ; 11 + DW Near Ptr BassVolumeLeft ; 12 + DW Near Ptr BassVolumeRight ; 13 + + DW Near Ptr MixFrequencyText + + DW 0 + +SB16HeaderLine DW 10 + DB "Sound Blaster 16 Lite Driver", 0 + +DriverText DW 1 + DB 31, 48 + DB 21h + DB "Sound Blaster 16 Driver 1.0 for Impulse Tracker", 0 + +VolumeText DW 1 + DB 2, 13 + DB 20h + DB "Master Volume Left", 13 + DB "Master Volume Right", 13 + DB 13 + DB 13 + DB "Treble Left", 13 + DB "Treble Right", 13 + DB "Bass Left", 13 + DB "Bass Right", 13 + DB 0 + +MixFrequencyText DW 1 + DB 2, 23 + DB 20h + DB "Playback Frequency: ", 0FDh, "DHz", 0 +MixSpeed DW 45454 + +VolumeBox1 DW 0 + DB 21, 12, 27, 15 + DB 25 + +VolumeBox2 DW 0 + DB 14, 16, 18, 21 + DB 25 + +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +IdleFunctionList DD 0 + DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +MasterVolumeLeft DW 9 + DB 22, 13 + DW 0, 31 + DW 9, 0 + DW 0FFFFh, 9, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +MasterVolumeRight DW 9 + DB 22, 14 + DW 0, 31 + DW 9, 1 + DW 8, 10, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +TrebleVolumeLeft DW 9 + DB 15, 17 + DW 0, 15 + DW 9, 2 + DW 9, 11, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +TrebleVolumeRight DW 9 + DB 15, 18 + DW 0, 15 + DW 9, 3 + DW 10, 12, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +BassVolumeLeft DW 9 + DB 15, 19 + DW 0, 15 + DW 9, 4 + DW 11, 13, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +BassVolumeRight DW 9 + DB 15, 20 + DW 0, 15 + DW 9, 5 + DW 12, 0FFFFh, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +VolumeTable DB 6 Dup (0) + +; ÄÄ MixingRoutines ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixBufferPos DW 0 + +include dma.inc +include mix.inc +include m12bit.mix + +MixFunctionTables Label + +include m12bit.inc ; contains the tables + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SBOut ; AL = data + ; DX = 2xCh + + Push AX + +SBOut1: + In AL, DX + Test AL, AL + JS SBOut1 + + Pop AX + Out DX, AL + + Ret + +EndP SBOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SBIn ; DX = 2xEh, returns AL + +SBIn1: + In AL, DX + Test AL, AL + JNS SBIn1 + + Add DL, 0Ah-0Eh ; DX = 2xAh -> Data read port + In AL, DX + Add DL, 0Eh-0Ah + + Ret + +EndP SBIn + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SBGetRegister + + Out DX, AL + Inc DX + In AL, DX + Dec DX + + Ret + +EndP SBGetRegister + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetSBMixConst ; Work out value.. and nearest + ; mixspeed value. + + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, CmdLineMixSpeed + Mov CX, MixSpeed + Test AX, AX + JZ GetSBMixConst1 + + Mov CX, 45454 + Cmp AX, CX + JA GetSBMixConst1 + + Mov CX, 12000 + Cmp AX, CX + JB GetSBMixConst1 + + Mov CX, AX + +GetSBMixConst1: + Mov AX, 1000 + Mul AX + Div CX + Mov AH, AL + Neg AH + Mov SBMixConst, AH + + MovZX BX, AL + Mov AX, 1000 + Mul AX + Div BX + Mov MixSpeed, AX + + Pop DS + PopA + Ret + +EndP GetSBMixConst + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetDSP Far ; AX = Port + + Push AX + Push CX + Push DX + + Mov DX, AX + Add DL, 6 + Mov AL, 1 + Out DX, AL + + In AL, DX + In AL, DX + In AL, DX + In AL, DX + + Xor AL, AL + Out DX, AL + + Add DL, 8 + Mov CX, 200 + +ResetDSP1: + In AL, DX + Test AL, AL + JS ResetDSP2 + Loop ResetDSP1 + Jmp ResetDSP3 + +ResetDSP2: + Sub DL, 4 + In AL, DX + Cmp AL, 0AAh + JE ResetDSP4 + Add DL, 4 + Loop ResetDSP1 + +ResetDSP3: + StC + +ResetDSP4: + Pop DX + Pop CX + Pop AX + Ret + +EndP ResetDSP + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetDSPIRQ + + Mov DX, CS:BasePort + Add DL, 4 + Mov AH, CS:DSPIRQValue + Mov AL, 80h + Out DX, AX + + Ret + +EndP ResetDSPIRQ + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetDSPDMA + + Mov DX, CS:BasePort + Add DL, 4 + Mov AH, CS:DSPDMAValue + Mov AL, 81h + Out DX, AX + + Ret + +EndP ResetDSPDMA + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far + + Push CS + Pop DS + Assume DS:Driver + + Mov Forced, AL + + Mov AX, BasePort + Cmp AX, 0FFFFh + JE DetectCard1 + + Cmp AX, 210h + JB DetectCard9 + Cmp AX, 280h + JA DetectCard9 + + Call ResetDSP + JNC DetectCard2 + + Ret + +DetectCard1: + Mov AX, 210h + +DetectCard2: + Call ResetDSP + JNC DetectCard3 + Add AL, 10h + Cmp AL, 80h + JBE DetectCard2 + +DetectCard9: + StC + Ret + +DetectCard3: ; OK... DSP found. + ; Get DSP version + Mov BasePort, AX + + Mov DX, AX + Add DL, 0Ch ; 2xCh -> Data ready to send... + +DetectCardOuputLoop1: + In AL, DX + Test AL, AL + JS DetectCardOuputLoop1 + + Mov AL, 0E1h ; Get DSP version command + Out DX, AL + + Add DL, 0Eh-0Ch ; DX = 2xEh -> Data available status + + Call SBIn + Mov AH, AL ; AH = Major version number + Call SBIn ; AL = Minor version number + + Cmp AH, 4 ; SB DSP = 4.00+ + JAE DetectCard5 + +DetectCard4: + StC + Ret + +DetectCard5: + Mov DSPVersion, AX + + Add DL, 04h-0Eh ; 2x4h = Mixer index port + Mov AL, 80h ; IRQ select + Out DX, AL + Inc DL ; 2x5h = Mixer data port + + In AL, DX + + Dec DL + + Mov DSPIRQValue, AL + ; OK.. now get IRQ, or set IRQ + Mov BX, IRQ + Cmp BX, 0FFFFh + JE DetectCardIRQ1 + Cmp Forced, 0 + JE DetectCardIRQ1 + + Mov AH, 11h + Cmp BL, 2 + JE SetCardIRQ1 + Cmp BL, 9 + JE SetCardIRQ1 + + Mov AH, 12h + Cmp BL, 5 + JE SetCardIRQ1 + + Mov AH, 14h + Cmp BL, 7 + JE SetCardIRQ1 + + Mov AH, 18h + Cmp BL, 10 + JE SetCardIRQ1 + + StC + Ret + +SetCardIRQ1: + Mov AL, 80h + Out DX, AL + Inc DL + Mov AL, AH + Out DX, AL + Dec DL + Jmp DetectCard6 + +DetectCardIRQ1: + Mov BX, 2 + Test AL, 1 + JNZ DetectCardIRQ2 + + Mov BL, 5 + Test AL, 2 + JNZ DetectCardIRQ2 + + Mov BL, 7 + Test AL, 4 + JNZ DetectCardIRQ2 + + Mov BL, 10 + Test AL, 8 + JNZ DetectCardIRQ2 + + StC + Ret + +DetectCardIRQ2: + Cmp IRQ, 0FFFFh + JE DetectCardIRQ3 + + Cmp BX, IRQ + JE DetectCard6 + + StC + Ret + +DetectCardIRQ3: + Mov IRQ, BX + +DetectCard6: ; Detect DMA + Mov AL, 81h ; DMA select + Out DX, AL + Inc DL + In AL, DX ; AL = DMA + Dec DL + + Mov DSPDMAValue, AL + + Mov BX, DMA + Cmp BX, 0FFFFh + JE DetectCardDMA1 + Cmp Forced, 0 + JE DetectCardDMA1 + + Mov CL, 1 + Cmp BX, 1 + JB SetCardDMA1 + + Mov CL, 2 + JE SetCardDMA1 + + Cmp BX, 3 + JB DetectCard7 + + Mov CL, 8 + JE DetectCard7 + + Mov CL, 20h + Cmp BX, 5 + JB DetectCard7 + JE SetCardDMA1 + + Mov CL, 80h + Cmp BX, 7 + JA DetectCard7 + JE SetCardDMA1 + + Mov CL, 40h + +SetCardDMA1: + And AL, 0Bh + Test CL, 0Bh + JZ SetCardDMA4 + + Xor AL, AL + +SetCardDMA4: + Or CL, AL + + Mov AL, 81h + Out DX, AL + Inc DL + Mov AL, CL + Out DX, AL + Jmp DetectCard7 + +DetectCardDMA1: + Mov BX, 5 + Test AL, 20h + JNZ DetectCardDMA2 + + Inc BL + Test AL, 40h + JNZ DetectCardDMA2 + + Inc BL + Test AL, 80h + JNZ DetectCardDMA2 + + Mov BL, 0 + Test AL, 1 + JNZ DetectCardDMA2 + + Inc BL + Test AL, 2 + JNZ DetectCardDMA2 + + Add BL, 2 + Test AL, 8 + JNZ DetectCardDMA2 + +DetectCard8: + Call ResetDSPIRQ + StC + Ret + +DetectCardDMA2: + Cmp DMA, 0FFFFh + JE DetectCardDMA3 + + Cmp BX, DMA + JNE DetectCard8 + +DetectCardDMA3: + Mov DMA, BX + +DetectCard7: + Mov EAX, 'Jeff' + + ClC + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc MixSamples ; Given DS:SI = info tables, CX = numchannels + + ; 1. Clean buffer + ; + update variables + ; 2. Update parameters + ; 3. Mix func + ; 4. Return + + Push CX + + Mov CX, BytesToMix + Mov ES, MixSegment + Mov DI, MIXTABLESIZE + Xor EAX, EAX + Mov DX, CX + + Mov MixTransferOffset, DI ; } Memory write + + Cmp Stereo, 0 + JE MixSamples1 + + Add DX, DX + +MixSamples1: + Rep StosD ; } Memory write + +MixSamplesCont: + Mov MixTransferRemaining, DX ; } + + Pop CX + +MixSamples2: + Test Byte Ptr [SI], 1 + JZ MixSamplesEnd2 + Cmp Byte Ptr [SI+36h], 100 + JE MixSamplesEnd2 + + Push CX + Mov CX, [SI] + + Test CH, 2 + JZ MixSamples3 + And Byte Ptr [SI], Not 1 + + Jmp MixSamplesEnd + +MixSamples3: + Test CL, 20h ; New freq? + JZ MixSamples5 + + Mov AX, [SI+10h] + Mov DX, [SI+12h] + Mov BX, MixSpeed + Cmp DX, BX + JAE MixSamplesHandleError + + Div BX + ShL EAX, 16 + Xor AX, AX + Div BX + Mov STEPVALUE, EAX + +MixSamples4: + Test CH, 1 + JZ MixSamples5 + + Mov DWord Ptr [SI+1Ch], 0 ; Current Volume = 0 + ; for volume sliding. +MixSamples5: + Test CX, 8440h ; New volume or panning? + JZ MixSamplesMix + + Xor AX, AX + Test CH, 8 ; Muted? + JNZ MixModeCommon + + Cmp Stereo, 0 + JNE Mix0ModeStereo + +Mix0Mode: ; 16-bit mixing, no interpolation +Mix0ModeMono: ; and 16-bit mixing, interpolation + Mov AL, [SI+20h] + ShR AL, 1 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 30 ; Use left only-mixing for mono + Jmp MixModeCommon + +Mix0ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix0ModeSurround + + Mul Byte Ptr [SI+20h] ; Final volume + Add AX, 64 + ShR AX, 7 + Mov [SI+0Ch], AX ; Store into right volume + + Mov AL, 64 + Sub AL, [SI+37h] + Mul Byte Ptr [SI+20h] + Add AX, 64 + ShR AX, 7 + Mov [SI+0Eh], AX ; Left volume + + Mov CH, AL ; CH = left volume + Mov CL, [SI+0Ch] ; CL = right volume + Mov AX, 0 + + Test CX, CX + JZ MixModeCommon + + Mov AL, 30 ; Left only... + Test CL, CL + JZ MixModeCommon + + Mov AL, 60 + Test CH, CH + JZ MixModeCommon + + Mov AL, 90 + Cmp CL, CH + JZ MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix0ModeSurround: + Mov AL, [SI+20h] + ShR AL, 2 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 150 ; Surround + Jmp MixModeCommon + +MixModeCommon: ; Requires AX = 30/60/90 etc. depending + ; On mixing mode type. + ; This will add 180 for 16-bit, + ; And sort out loop types. + Mov BL, [SI+0Ah] + Test Byte Ptr [SI+18h], 2 ; 16 bit? + JZ MixModeCommon1 + + Add AX, 180 + +MixModeCommon1: + Cmp BL, 8 + JB MixModeCommon3 ; No loop + JE MixModeCommon2 ; Forwards loop + + Add AX, 10 + +MixModeCommon2: + Add AX, 10 + +MixModeCommon3: + Add AX, Offset MixFunctionTables + Mov [SI+8], AX ; Offset... + +MixSamplesMix: + Mov BX, [SI+8] ; BX = offset into + Mov EAX, [CS:BX+2] + Mov DWord Ptr PreMixFunction, EAX + Mov EAX, [CS:BX+6] + Mov DWord Ptr MixFunctionSeparateBackwards, EAX + + Mov AX, BytesToMix + Mov MixBlockSize, AX + Mov MixBufferOffset, MIXTABLESIZE + + Mov EAX, CURRENTPOSITION + Mov OLDPOSITION, EAX + + Call Word Ptr [CS:BX] + + And Word Ptr [SI], 0111100010001101b + Jmp MixSamplesEnd + +MixSamplesHandleError: + Mov Word Ptr [SI], 200h + + Test Byte Ptr [SI+3Ah], 80h + JNZ MixSamplesEnd + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Turn off channel + +MixSamplesEnd: + Pop CX + +MixSamplesEnd2: + Add SI, 128 + Dec CX + JNZ MixSamples2 + + Ret + +EndP MixSamples + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc AckIRQ + Assume DS:Driver + + Mov AL, 20h + Cmp IRQ, 7 + JBE AckIRQ1 + + Out 0A0h, AL + +AckIRQ1: + Out 20h, AL + Ret + +EndP AckIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SB16IRQHandler + + PushAD + Push DS + Push ES + + CLD + + Mov AX, CS + Mov DS, AX + Assume DS:Driver + + Mov DX, BasePort + Add DL, 0Fh + In AL, DX + + Call AckIRQ + + Mov AX, MixBufferPos + Mov BX, AX + Mul DMASize + Cmp AX, DMABUFFERLENGTH + JB SB16IRQHandler2 + + Xor AX, AX + Xor BX, BX + +SB16IRQHandler2: + Inc BX + Mov MixBufferPos, BX + + + ; OK... time to get next block + ; Check whether stereo thing is on.. + ; + LES DI, [ActualDMAPtr] + Add DI, AX + + Mov BX, DMASize ; BX = bytes required + ShR BX, 1 + ; BX = samples required + Mov BP, 4 ; Skip for mono + Mov CL, 2 ; Shift for mono + + Cmp Stereo, 0 + JE SB16IRQHandlerMono + + ShR BP, 1 + Inc CL + +SB16IRQHandlerMono: + Call SaveEMSPageFrame + + Cmp MixTransferRemaining, 0 + JNE SB16IRQHandler4 + Assume DS:Nothing + +SB16IRQHandler3: + Push BX + Push CX + Push BP + Push ES + Push DI + + Call Update + Call MixSamples + + Pop DI + Pop ES + Pop BP + Pop CX + Pop BX + +SB16IRQHandler4: + Mov DS, MixSegment + Mov SI, MixTransferOffset + Mov DX, BX ; DX = samples to transfer + Cmp DX, MixTransferRemaining + JBE SB16IRQHandler5 + + Mov DX, MixTransferRemaining + +SB16IRQHandler5: + Push DX + +SB16IRQHandler6: + MovSX EAX, Word Ptr [SI] + SAL EAX, CL + + Cmp EAX, -8000h + JL SB16IRQHandlerClip1 + Cmp EAX, 7FFFh + JG SB16IRQHandlerClip2 + +SB16IRQHandler7: + StosW ; } Memory write + + Add SI, BP + Dec DX + JNZ SB16IRQHandler6 + +SB16MixTransferEnd: + Pop DX + + Sub MixTransferRemaining, DX ; } Memory write + Sub BX, DX + JNZ SB16IRQHandler3 + + Mov MixTransferOffset, SI ; } Memory write + + Call RestoreEMSPageFrame + +SBIRQEnd: + Pop ES + Pop DS + PopAD + IRet + +SB16IRQHandlerClip1: + Mov AX, 8000h + Jmp SB16IRQHandler7 + +SB16IRQHandlerClip2: + Mov AX, 7FFFh + Jmp SB16IRQHandler7 + +EndP SB16IRQHandler + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + + PushAD + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Add DI, Offset IRQData + Mov BX, [DI] + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset SB16IRQHandler + + XChg [ES:BX], EAX + Mov OldIRQHandler, EAX + + Mov AX, IMR + And AX, [DI+2] + + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Pop ES + Pop DS + PopAD + + Ret + +EndP SetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIRQ + + PushAD + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Mov BX, [IRQData+DI] + + Mov EAX, OldIRQHandler + Mov [ES:BX], EAX + + Pop ES + Pop DS + PopAD + + Ret + +EndP ResetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StartSB16 ; + + PushA + Push ES + + ; Setup DMA + Mov BX, DMASegment + Xor AX, AX + Mov DX, DMA + Mov DI, DMABUFFERLENGTH + Call SetDMA + + LES DI, ActualDMAPtr + Xor AX, AX + Mov CX, DMABUFFERLENGTH/2 + Rep StosW + + Mov MixBufferPos, 0 + Mov MixTransferRemaining, 0 + + Mov DX, BasePort + Add DL, 0Ch + + Mov AL, 0D1h ; turn on speaker + Call SBOut + + Mov AL, 40h ; time constant + Call SBOut + Mov AL, SBMixConst + Call SBOut + + Mov AL, 0B6h ; 16 bit, DAC + Call SBOut + Mov AL, Stereo + ShL AL, 5 + Or AL, 10h + Call SBOut + + Mov AX, DMASize + ShR AX, 1 + Dec AX + + Call SBOut ; DMALength, Lo + Mov AL, AH + Call SBOut + + Pop ES + PopA + + Ret + + Assume DS:Nothing + +EndP StartSB16 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixerRegisters + + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Pop DS + + Ret + +EndP GetMixerRegisters + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Call GetEMSPageFrame + Mov EMSPageFrame, AX + + In AL, 0A1h + Mov AH, AL + In AL, 21h + Mov IMR, AX + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + Mov DX, BasePort + Add DL, 4 + + Mov AL, 30h + Call SBGetRegister + ShR AL, 3 + Mov VolumeTable, AL + + Mov AL, 31h + Call SBGetRegister + ShR AL, 3 + Mov [VolumeTable+1], AL + + Mov AL, 44h + Call SBGetRegister + ShR AL, 4 + Mov [VolumeTable+2], AL + + Mov AL, 45h + Call SBGetRegister + ShR AL, 4 + Mov [VolumeTable+3], AL + + Mov AL, 46h + Call SBGetRegister + ShR AL, 4 + Mov [VolumeTable+4], AL + + Mov AL, 47h + Call SBGetRegister + ShR AL, 4 + Mov [VolumeTable+5], AL + + Call GetSBMixConst + + ; Parags to allocate = (4/(.4*31*16))*MixSpeed + 2080 + ; = .02016129*MixSpeed = (65536*.04032258*MixSpeed) / 65536 + + Mov AX, 1322 + Mul MixSpeed + Add AX, 0FFFFh + AdC DX, 2080 + + Mov BX, (DMABUFFERLENGTH*2)/16 + Add BX, DX + + ; Allocate MixSegment first + Mov AH, 48h + + Int 21h + JNC InitSound1 + +InitSoundNoMemory: + Mov SI, Offset SB16NoMemoryMsg + Ret + +InitSound1: + Mov MixSegment, AX + Add AX, DX + Mov DMASegment, AX + Sub DX, 2080 + Mov MixSegmentLength, DX + + Call SetIRQ + Call GetTempo + Call SetTempo + + Mov SI, Offset SB16Msg + + Mov AX, BasePort + Mov BX, IRQ + Mov CX, DMA + + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, BasePort + Mov DX, AX + Call ResetDSP + + Call ResetIRQ + ; Delay.. + Mov DX, BasePort + Add DL, 0Ch + + Mov CX, 1000 +ReInitSound1: + In AL, DX + Loop ReInitSound1 + + Call SetIRQ + + Mov SI, Offset ReInitMsg + Mov BX, 40 + Call SetInfoLine + + Mov AL, Stereo + Call SetStereo + + Pop ES + Pop DS + PopA + + Ret + +EndP ReInitSound + Assume DS:Nothing + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Mov DX, CS:BasePort + Add DL, 0Ch + + Mov AL, 0D3h + Call SBOut + + Mov AL, 0D5h + Call SBOut + + Mov AL, 0D9h + Call SBOut + + Mov AL, 0D5h + Call SBOut + + Mov AX, BasePort + Call ResetDSP + + Call ResetDSPDMA + Call ResetDSPIRQ + + Mov AX, IMR + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Mov AX, MixSegment + Test AX, AX + JZ UnInitSound1 + + Mov ES, AX + Mov AH, 49h ; Release MixSegment + Int 21h + + Call ResetIRQ + +UnInitSound1: + Ret + +EndP UnInitSound + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + Ret + +EndP Poll + Assume DS:Nothing + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Push AX + Push BX + Push DX + + Push BX + + Mov AX, MixSpeed + Mov BX, AX + Xor DX, DX + + ShL AX, 1 + RCL DX, 1 ; DX:AX = Mixspeed*2 + + ShR BX, 1 ; BX = Mixspeed/2 + + Add AX, BX + AdC DX, 0 ; DX:AX = Mixspeed*2.5 + + Pop BX ; BX = tempo + Div BX + + Mov BytesToMix, AX + + Pop DX + Pop BX + Pop AX + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + PushA + Push DS + + Mov BX, AX ; BX = MixVolume + + Mov AX, CS:MixSegment + Test AX, AX + JZ SetMixVolume2 + + Mov DS, AX + + Mov CX, MIXTABLESIZE/2 + Mov SI, MIXTABLESIZE-2; Starting point - working backwards + +SetMixVolume1: + Mov AX, CX + + Dec AX ; AH = volume, AL = wave value. + Xor DX, DX + XChg AH, DL ; DL = Volume, AX = wave value + CBW + + IMul DX ; DX:AX = Volume * Wave Value + ; Ranges -8192->8128 + + IMul BX ; DX:AX = Volume * Wave Value * Mixing Volume + ; Ranges -1048576->1040384 + + Add AX, 64 + AdC DX, 0 + + ShRD AX, DX, 7 + Mov [SI], AX + Sub SI, 2 + + Dec CX + JNZ SetMixVolume1 + +SetMixVolume2: + Pop DS + PopA + + Ret + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Cmp CS:MixSegment, 0 + JE SetStereo1 + + Mov CS:Stereo, AL + Mov AX, CS:BasePort + Call ResetDSP + + Mov ES, CS:MixSegment + Mov CX, CS:MixSegmentLength + Mov DI, MIXTABLESIZE + ShL CX, 2 + Xor EAX, EAX + Rep StosD + + Call StartSB16 + +SetStereo1: + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include loadsam.inc + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset SB16ScreenList + + ClC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far ; Returns AX, given DI + + Xor AH, AH + Mov AL, [CS:VolumeTable+DI] + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far ; Given AX, DI + + Push DS + Push DX + + Push CS + Pop DS + Assume DS:Driver + + Mov [VolumeTable+DI], AL + + Mov DX, BasePort + Add DL, 4 + Mov AL, 30h + Mov AH, [VolumeTable] + ShL AH, 3 + Out DX, AX + + Mov AL, 31h + Mov AH, [VolumeTable+1] + ShL AH, 3 + Out DX, AX + + Mov AL, 44h + Mov AH, [VolumeTable+2] + ShL AH, 4 + Out DX, AX + + Mov AL, 45h + Mov AH, [VolumeTable+3] + ShL AH, 4 + Out DX, AX + + Mov AL, 46h + Mov AH, [VolumeTable+4] + ShL AH, 4 + Out DX, AX + + Mov AL, 47h + Mov AH, [VolumeTable+5] + ShL AH, 4 + Out DX, AX + + Pop DX + Pop DS + Ret + +EndP SetVariable + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. + +StopAfterPlay DW 0 +DefaultChannels DW 64 + DW 5 Dup (0) + + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/SB16D.ASM b/SoundDrivers/SB16D.ASM new file mode 100755 index 0000000..f50716c --- /dev/null +++ b/SoundDrivers/SB16D.ASM @@ -0,0 +1,2665 @@ + + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;********************************** + +STEREOENABLED EQU 1 +DMABUFFERLENGTH EQU 4096 +MIXRESOLUTION EQU 32 ; 32 bit mixing for the SB16 +MIXTABLESIZE EQU 2*256*65 +FOURIERBUFFERLENGTH EQU 2048 + +SB16Msg DB "Sound Blaster 16 detected", 13 + DB "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, DMA ", 0FDh, "D", 0 + +SB16NoMemoryMsg DB "Sound Blaster 16 detected", 13 + DB "Error: Insufficient memory", 0 + +ReinitMsg DB "Sound Blaster 16 reinitialised", 0 + +ConfigErrorMsg DB "Error saving configuration to ITSB16.DRV", 0 +ConfigOKMsg DB "Configuration saved to ITSB16.DRV", 0 + +DriverName DB "ITSB16.DRV", 0 + +DSPVersion DW 0 +DSPIRQValue DB 0 +DSPDMAValue DB 0 +Forced DB 0 +Stereo DB 0 +MixVolume DW 0 +; MixVolumeSet DW 0 + +BytesToMix DW 1000 +SBMixConst DB 0 + +MixSegment DW 0 +DMASegment DW 0 +FourierSegment DW 0 +MixSegmentLength DW 0 + +MixTransferOffset DW 0 +MixTransferRemaining DW 0 + +CONFIGURATIONOFFSET EQU $+128 +CONFIGSIZE EQU 10 +MixMode DW 0 +MixModeOffset DW 0 +Filter DW 0 +Surround DW 0 +DMASize DW 2048 + +IMR DW 0 +OldIRQHandler DD 0 + +FilterValue DD 0 +FilterValue2 DD 0 + +MIDIPort DW 0 +MIDIBuffer DB 256 Dup (0) +MIDIBufferHead DB 0 +MIDIBufferTail DB 0 + +IRQData Label Word + DW 20h, 1111111111111110b ; IRQ 0 + DW 24h, 1111111111111101b ; IRQ 1 + DW 28h, 1111110111111011b ; IRQ 2 + DW 2Ch, 1111111111110111b ; IRQ 3 + DW 30h, 1111111111101111b ; IRQ 4 + DW 34h, 1111111111011111b ; IRQ 5 + DW 38h, 1111111110111111b ; IRQ 6 + DW 3Ch, 1111111101111111b ; IRQ 7 + DW 1C0h, 1111111011111011b ; IRQ 8 + DW 1C4h, 1111110111111011b ; IRQ 9 + DW 1C8h, 1111101111111011b ; IRQ 10 + DW 1CCh, 1111011111111011b ; IRQ 11 + DW 1D0h, 1110111111111011b ; IRQ 12 + DW 1D4h, 1101111111111011b ; IRQ 13 + DW 1D8h, 1011111111111011b ; IRQ 14 + DW 1DCh, 0111111111111011b ; IRQ 15 + + +;********************************** + +SB16ScreenList Label + DW 8 + DW Near Ptr IdleFunctionList + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr SB16HeaderLine + + DW Near Ptr VolumeText + DW Near Ptr VolumeBox1 + DW Near Ptr VolumeBox2 + + DW Near Ptr DriverText + + DW Near Ptr MasterVolumeLeft ; 8 + DW Near Ptr MasterVolumeRight ; 9 + DW Near Ptr TrebleVolumeLeft ; 10 + DW Near Ptr TrebleVolumeRight ; 11 + DW Near Ptr BassVolumeLeft ; 12 + DW Near Ptr BassVolumeRight ; 13 + + DW Near Ptr MixModeText + DW Near Ptr MixModeButton1 ; 15 + DW Near Ptr MixModeButton2 ; 16 + DW Near Ptr MixModeButton3 ; 17 + DW Near Ptr MixModeButton4 ; 18 + + DW Near Ptr FilterText + DW Near Ptr FilterButton1 ; 20 + DW Near Ptr FilterButton2 ; 21 + DW Near Ptr FilterButton3 ; 22 + + DW Near Ptr StereoText + DW Near Ptr StereoButton1 ; 24 + DW Near Ptr StereoButton2 ; 25 + DW Near Ptr StereoButton3 ; 25 + + DW Near Ptr FrequencyText + + DW 0 + + +SB16HeaderLine DW 10 + DB "Sound Blaster 16 Driver", 0 + +DriverText DW 1 + DB 31, 48 + DB 21h + DB "Sound Blaster 16 Driver 1.4 for Impulse Tracker", 0 + +VolumeText DW 1 + DB 2, 13 + DB 20h + DB "Master Volume Left", 13 + DB "Master Volume Right", 13 + DB 13 + DB 13 + DB "Treble Left", 13 + DB "Treble Right", 13 + DB "Bass Left", 13 + DB "Bass Right", 13 + DB 0 + +VolumeBox1 DW 0 + DB 21, 12, 27, 15 + DB 25 + +VolumeBox2 DW 0 + DB 14, 16, 18, 21 + DB 25 + +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +IdleFunctionList DD 0 + DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +MasterVolumeLeft DW 9 + DB 22, 13 + DW 0, 31 + DW 9, 0 + DW 0FFFFh, 9, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +MasterVolumeRight DW 9 + DB 22, 14 + DW 0, 31 + DW 9, 1 + DW 8, 10, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +TrebleVolumeLeft DW 9 + DB 15, 17 + DW 0, 15 + DW 9, 2 + DW 9, 11, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +TrebleVolumeRight DW 9 + DB 15, 18 + DW 0, 15 + DW 9, 3 + DW 10, 12, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +BassVolumeLeft DW 9 + DB 15, 19 + DW 0, 15 + DW 9, 4 + DW 11, 13, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +BassVolumeRight DW 9 + DB 15, 20 + DW 0, 15 + DW 9, 5 + DW 12, 15, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +MixModeText DW 1 + DB 2, 23 + DB 20h + DB "Mixing Mode", 0 + +FrequencyText DW 1 + DB 2, 48 + DB 20h + DB "Playback Frequency: ", 0FDh, "DHz", 0 +MixSpeed DW 45454 + +MixModeButton1 DW 2 + DW 13, 16, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment1 DW 0 + DW 0 + DW Offset SetMixMode +DriverSegment2 DW 0 + DB 3, 25, 32, 27, 8 + DB 0 + DB " 16 Bit, Non-Interpolated", 0 + +MixModeButton2 DW 2 + DW 15, 17, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment3 DW 0 + DW 2 + DW Offset SetMixMode +DriverSegment4 DW 0 + DB 3, 28, 32, 30, 8 + DB 0 + DB " 16 Bit, Interpolated", 0 + +MixModeButton3 DW 2 + DW 16, 18, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment5 DW 0 + DW 4 + DW Offset SetMixMode +DriverSegment6 DW 0 + DB 3, 31, 32, 33, 8 + DB 0 + DB " 32 Bit, Non-Interpolated", 0 + +MixModeButton4 DW 2 + DW 17, 20, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment7 DW 0 + DW 6 + DW Offset SetMixMode +DriverSegment8 DW 0 + DB 3, 34, 32, 36, 8 + DB 0 + DB " 32 Bit, Interpolated", 0 + +FilterText DW 1 + DB 40, 13 + DB 20h + DB "Filter mode", 0 + +FilterButton1 DW 2 + DW 18, 21, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment9 DW 0 + DW 0 + DW Offset SetFilter +DriverSegment10 DW 0 + DB 42, 15, 60, 17, 8 + DB 0 + DB " No Filter", 0 + +FilterButton2 DW 2 + DW 20, 22, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment11 DW 0 + DW 1 + DW Offset SetFilter +DriverSegment12 DW 0 + DB 42, 18, 60, 20, 8 + DB 0 + DB " 50% Filter", 0 + +FilterButton3 DW 2 + DW 21, 24, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment13 DW 0 + DW 2 + DW Offset SetFilter +DriverSegment14 DW 0 + DB 42, 21, 60, 23, 8 + DB 0 + DB " 75% Filter", 0 + +StereoText DW 1 + DB 40, 25 + DB 20h + DB "Feedback mode", 0 + +StereoButton1 DW 2 + DW 22, 25, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetSurround +DriverSegment15 DW 0 + DW 0 + DW Offset SetSurround +DriverSegment16 DW 0 + DB 42, 27, 60, 29, 8 + DB 0 + DB " None", 0 + +StereoButton2 DW 2 + DW 24, 26, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetSurround +DriverSegment17 DW 0 + DW 1 + DW Offset SetSurround +DriverSegment18 DW 0 + DB 42, 30, 60, 32, 8 + DB 0 + DB " 50% Separated", 0 + +StereoButton3 DW 2 + DW 25, 0FFFFh, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetSurround +DriverSegment19 DW 0 + DW 2 + DW Offset SetSurround +DriverSegment20 DW 0 + DB 42, 33, 60, 35, 8 + DB 0 + DB " 50% Crossed", 0 + + +VolumeTable DB 6 Dup (0) + +; ÄÄ MixingRoutines ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include dmasirq.inc +include mix.inc +include m12bit.mix +include m12biti.mix +include m32bit.mix +include m32biti.mix + +MixFunctionTables Label + +include m12bit.inc ; contains the tables +include m12biti.inc +include m32bit.inc +include m32biti.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +RelocationTable Label Word + DW Offset DriverSegment1, Offset DriverSegment2 + DW Offset DriverSegment3, Offset DriverSegment4 + DW Offset DriverSegment5, Offset DriverSegment6 + DW Offset DriverSegment7, Offset DriverSegment8 + DW Offset DriverSegment9, Offset DriverSegment10 + DW Offset DriverSegment11, Offset DriverSegment12 + DW Offset DriverSegment13, Offset DriverSegment14 + DW Offset DriverSegment15, Offset DriverSegment16 + DW Offset DriverSegment17, Offset DriverSegment18 + DW Offset DriverSegment19, Offset DriverSegment20 + DW 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SBOut ; AL = data + ; DX = 2xCh + + Push AX + +SBOut1: + In AL, DX + Test AL, AL + JS SBOut1 + + Pop AX + Out DX, AL + + Ret + +EndP SBOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SBIn ; DX = 2xEh, returns AL + +SBIn1: + In AL, DX + Test AL, AL + JNS SBIn1 + + Add DL, 0Ah-0Eh ; DX = 2xAh -> Data read port + In AL, DX + Add DL, 0Eh-0Ah + + Ret + +EndP SBIn + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectUART ; Given DX = Port + +; From SB-DevKit + + ClI + + Inc DX + Xor CX, CX + +DetectUART1: + In AL, DX + Test AL, 40h ; Ready for output + LoopNZ DetectUART1 + JNZ DetectUARTError + + Mov AL, 0FFh ; Reset! + Out DX, AL + + Xor CX, CX + +DetectUART2: + In AL, DX + Test AL, 80h + JNZ DetectUART3 + + Dec DX + In AL, DX + Inc DX + Cmp AL, 0FEh + JE DetectUART4 + +DetectUART3: + Loop DetectUART2 + +DetectUARTError: + StI + StC + Ret + +DetectUART4: ; Now to shove it into 'intelligent' mode. + Xor CX, CX + +DetectUART5: + In AL, DX + Test AL, 40h + LoopNZ DetectUART5 + JNZ DetectUARTError + + Mov AL, 3Fh ; Intelligent mode! + Out DX, AL + +DetectUART6: + Xor CX, CX + +DetectUART7: + In AL, DX + Test AL, 80h + JNZ DetectUART8 + + Dec DX + In AL, DX + Inc DX + Cmp AL, 0FEh + JE DetectUART9 + +DetectUART8: + Loop DetectUART7 + + Jmp DetectUARTError + +DetectUART9: + StI + ClC + Ret + +EndP DetectUART + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReinitUART + + Mov DX, MIDIPort + Test DX, DX + JZ ReinitUART1 + + Call DetectUART + +ReinitUART1: + Ret + +EndP ReinitUART + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetUART + + Mov DX, MIDIPort + Test DX, DX + JZ ResetUART1 + + Inc DX + + Mov AL, 0FFh + Out DX, AL + +ResetUART1: + Ret + +EndP ResetUART + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixMode Far + + Push CS + Pop ES + Mov DI, Offset MixMode + + Ret + +EndP GetMixMode + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetFilter Far + + Push CS + Pop ES + Mov DI, Offset Filter + + Ret + +EndP GetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetFilter Far + + Mov AX, [SI+22] + Mov CS:FilterValue, 0 + Mov CS:Filter, AX + Jmp SetMixModeChain + +EndP SetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetSurround Far + + Push CS + Pop ES + Mov DI, Offset Surround + + Ret + +EndP GetSurround + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetSurround Far + + Mov AX, [SI+22] + Mov CS:Surround, AX + +; Mov AX, CS:MixVolumeSet +; Call Far Ptr SetMixVolumeChain + + Jmp SetMixModeChain + +EndP SetSurround + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixMode Far + + Mov AX, [SI+22] + + ClI + + Mov CS:MixMode, AX + + Mov BX, 180 + Mul BX + Mov CS:MixModeOffset, AX + + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS:RecalculateAllVolumes + + StI + +SetMixModeChain: + Call GotoHomeDirectory + + ; Now to save config into driver file. + Push CS + Pop DS + Assume DS:Driver + + Mov AX, 3D02h ; Read write access + Mov DX, Offset DriverName + Mov SI, Offset ConfigErrorMsg + Int 21h + JC SetMixMode1 + + Mov BX, AX + + Mov AX, 4200h + Xor CX, CX + Mov DX, Offset CONFIGURATIONOFFSET + Int 21h + JC SetMixMode2 + + Mov AH, 40h + Mov CX, CONFIGSIZE + Mov DX, Offset MixMode + Int 21h + +SetMixMode2: + PushF + Mov AH, 3Eh + Int 21h + PopF + + JC SetMixMode1 + + Mov SI, Offset ConfigOKMsg + +SetMixMode1: + Mov BX, 40 + Call SetInfoLine + + Mov AX, 1 + Ret + +EndP SetMixMode + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SBGetRegister + + Out DX, AL + Inc DX + In AL, DX + Dec DX + + Ret + +EndP SBGetRegister + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetSBMixConst ; Work out value.. and nearest + ; mixspeed value. + + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, CmdLineMixSpeed + Mov CX, MixSpeed + Test AX, AX + JZ GetSBMixConst1 + + Mov CX, 45454 + Cmp AX, CX + JA GetSBMixConst1 + + Mov CX, 12000 + Cmp AX, CX + JB GetSBMixConst1 + + Mov CX, AX + +GetSBMixConst1: + Mov AX, 1000 + Mul AX + Div CX + Mov AH, AL + Neg AH + Mov SBMixConst, AH + + MovZX BX, AL + Mov AX, 1000 + Mul AX + Div BX + Mov MixSpeed, AX + + Mov BX, 12000 + Xor DX, DX + Div BX + Mov FourierBufferStepOffset, AX + Mov FourierBufferStepFractional, DX + + Pop DS + PopA + Ret + +EndP GetSBMixConst + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetDSP Far ; AX = Port + + Push AX + Push CX + Push DX + + Mov DX, AX + Add DL, 6 + Mov AL, 1 + Out DX, AL + + In AL, DX + In AL, DX + In AL, DX + In AL, DX + + Xor AL, AL + Out DX, AL + + Add DL, 8 + Mov CX, 200 + +ResetDSP1: + In AL, DX + Test AL, AL + JS ResetDSP2 + Loop ResetDSP1 + Jmp ResetDSP3 + +ResetDSP2: + Sub DL, 4 + In AL, DX + Cmp AL, 0AAh + JE ResetDSP4 + Add DL, 4 + Loop ResetDSP1 + +ResetDSP3: + StC + +ResetDSP4: + Pop DX + Pop CX + Pop AX + Ret + +EndP ResetDSP + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetDSPIRQ + + Mov DX, CS:BasePort + Add DL, 4 + Mov AH, CS:DSPIRQValue + Mov AL, 80h + Out DX, AX + + Ret + +EndP ResetDSPIRQ + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetDSPDMA + + Mov DX, CS:BasePort + Add DL, 4 + Mov AH, CS:DSPDMAValue + Mov AL, 81h + Out DX, AX + + Ret + +EndP ResetDSPDMA + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far + + Push CS + Pop DS + Assume DS:Driver + + Mov Forced, AL + + Mov AX, BasePort + Cmp AX, 0FFFFh + JE DetectCard1 + + Cmp AX, 210h + JB DetectCard9 + Cmp AX, 280h + JA DetectCard9 + + Call ResetDSP + JNC DetectCard2 + + Ret + +DetectCard1: + Mov AX, 210h + +DetectCard2: + Call ResetDSP + JNC DetectCard3 + Add AL, 10h + Cmp AL, 80h + JBE DetectCard2 + +DetectCard9: + StC + Ret + +DetectCard3: ; OK... DSP found. + ; Get DSP version + Mov BasePort, AX + + Mov DX, AX + Add DL, 0Ch ; 2xCh -> Data ready to send... + +DetectCardOuputLoop1: + In AL, DX + Test AL, AL + JS DetectCardOuputLoop1 + + Mov AL, 0E1h ; Get DSP version command + Out DX, AL + + Add DL, 0Eh-0Ch ; DX = 2xEh -> Data available status + + Call SBIn + Mov AH, AL ; AH = Major version number + Call SBIn ; AL = Minor version number + + Cmp AH, 4 ; SB DSP = 4.00+ + JAE DetectCard5 + +DetectCard4: + StC + Ret + +DetectCard5: + Mov DSPVersion, AX + + Add DL, 04h-0Eh ; 2x4h = Mixer index port + Mov AL, 80h ; IRQ select + Out DX, AL + Inc DL ; 2x5h = Mixer data port + + In AL, DX + + Dec DL + + Mov DSPIRQValue, AL + ; OK.. now get IRQ, or set IRQ + Mov BX, IRQ + Cmp BX, 0FFFFh + JE DetectCardIRQ1 + Cmp Forced, 0 + JE DetectCardIRQ1 + + Mov AH, 11h + Cmp BL, 2 + JE SetCardIRQ1 + Cmp BL, 9 + JE SetCardIRQ1 + + Mov AH, 12h + Cmp BL, 5 + JE SetCardIRQ1 + + Mov AH, 14h + Cmp BL, 7 + JE SetCardIRQ1 + + Mov AH, 18h + Cmp BL, 10 + JE SetCardIRQ1 + + StC + Ret + +SetCardIRQ1: + Mov AL, 80h + Out DX, AL + Inc DL + Mov AL, AH + Out DX, AL + Dec DL + Jmp DetectCard6 + +DetectCardIRQ1: + Mov BX, 2 + Test AL, 1 + JNZ DetectCardIRQ2 + + Mov BL, 5 + Test AL, 2 + JNZ DetectCardIRQ2 + + Mov BL, 7 + Test AL, 4 + JNZ DetectCardIRQ2 + + Mov BL, 10 + Test AL, 8 + JNZ DetectCardIRQ2 + + StC + Ret + +DetectCardIRQ2: + Cmp IRQ, 0FFFFh + JE DetectCardIRQ3 + + Cmp BX, IRQ + JE DetectCard6 + + StC + Ret + +DetectCardIRQ3: + Mov IRQ, BX + +DetectCard6: ; Detect DMA + Mov AL, 81h ; DMA select + Out DX, AL + Inc DL + In AL, DX ; AL = DMA + Dec DL + + Mov DSPDMAValue, AL + + Mov BX, DMA + Cmp BX, 0FFFFh + JE DetectCardDMA1 + Cmp Forced, 0 + JE DetectCardDMA1 + + Mov CL, 1 + Cmp BX, 1 + JB SetCardDMA1 + + Mov CL, 2 + JE SetCardDMA1 + + Cmp BX, 3 + JB DetectCard7 + + Mov CL, 8 + JE DetectCard7 + + Mov CL, 20h + Cmp BX, 5 + JB DetectCard7 + JE SetCardDMA1 + + Mov CL, 80h + Cmp BX, 7 + JA DetectCard7 + JE SetCardDMA1 + + Mov CL, 40h + +SetCardDMA1: + And AL, 0Bh + Test CL, 0Bh + JZ SetCardDMA4 + + Xor AL, AL + +SetCardDMA4: + Or CL, AL + + Mov AL, 81h + Out DX, AL + Inc DL + Mov AL, CL + Out DX, AL + Jmp DetectCard7 + +DetectCardDMA1: + Mov BX, 5 + Test AL, 20h + JNZ DetectCardDMA2 + + Inc BL + Test AL, 40h + JNZ DetectCardDMA2 + + Inc BL + Test AL, 80h + JNZ DetectCardDMA2 + + Mov BL, 0 + Test AL, 1 + JNZ DetectCardDMA2 + + Inc BL + Test AL, 2 + JNZ DetectCardDMA2 + + Add BL, 2 + Test AL, 8 + JNZ DetectCardDMA2 + +DetectCard8: + Call ResetDSPIRQ + StC + Ret + +DetectCardDMA2: + Cmp DMA, 0FFFFh + JE DetectCardDMA3 + + Cmp BX, DMA + JNE DetectCard8 + +DetectCardDMA3: + Mov DMA, BX + +DetectCard7: + Mov EAX, 'Jeff' + + ClC + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixModeTable Label Word + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + +Proc MixSamples ; Given DS:SI = info tables, CX = numchannels + + ; 1. Clean buffer + ; + update variables + ; 2. Update parameters + ; 3. Mix func + ; 4. Return + + Push CX + + Mov CX, BytesToMix + Mov ES, MixSegment + Mov DI, MIXTABLESIZE + Mov DX, CX + Add CX, CX + + Mov MixTransferOffset, DI ; } Memory write + + Cmp Stereo, 0 + JE MixSamples1 + + Mov DX, CX + + Cmp Surround, 1 + JB MixSamplesCont + + Push DS + + Push ES + Pop DS + + JE MixSurround3 + +Surround1: + Mov EAX, [DI+4] + Mov EBX, [DI] + SAR EAX, 1 + SAR EBX, 1 + Mov [DI], EAX + Mov [DI+4], EBX + + Add DI, 8 + Sub CX, 2 + JNZ Surround1 + + Pop DS + Jmp SurroundCont + +MixSamples1: + Cmp Surround, 1 + JB MixSamplesCont + +MixSurround2: + Push DS + + Push ES + Pop DS + +MixSurround3: + SAR DWord Ptr [DI], 1 + Add DI, 4 + Dec CX + JNZ MixSurround3 + + Pop DS + Jmp SurroundCont + +MixSamplesCont: + Xor EAX, EAX + Rep StosD ; } Memory write + +SurroundCont: + Mov MixTransferRemaining, DX ; } + + Pop CX + +MixSamples2: + Test Byte Ptr [SI], 1 + JZ MixSamplesEnd2 + Cmp Byte Ptr [SI+36h], 100 + JE MixSamplesEnd2 + + Push CX + Mov CX, [SI] + + Test CH, 2 + JZ MixSamples3 + And Byte Ptr [SI], Not 1 + + Jmp MixSamplesEnd +; Cmp MixMode, 8 ; Is it volume ramping? +; JB MixSamplesEnd + +MixSamples3: + Test CL, 20h ; New freq? + JZ MixSamples5 + + Mov AX, [SI+10h] + Mov DX, [SI+12h] + Mov BX, MixSpeed + Cmp DX, BX + JAE MixSamplesHandleError + + Div BX + ShL EAX, 16 + Xor AX, AX + Div BX + Mov STEPVALUE, EAX + +MixSamples4: + Test CH, 1 + JZ MixSamples5 + + Mov DWord Ptr [SI+1Ch], 0 ; Current Volume = 0 + ; for volume sliding. +MixSamples5: + Test CX, 8440h ; New volume or panning? + JZ MixSamplesMix + + Xor AX, AX + Test CH, 8 ; Muted? + JNZ MixModeCommon + + Mov BX, MixMode + Add BL, Stereo + Add BX, BX + Jmp [CS:MixModeTable+BX] + +Mix0Mode: ; 16-bit mixing, no interpolation +Mix0ModeMono: ; and 16-bit mixing, interpolation + Mov AL, [SI+20h] + ShR AL, 1 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 30 ; Use left only-mixing for mono + Jmp MixModeCommon + +Mix0ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix0ModeSurround + + Mul Byte Ptr [SI+20h] ; Final volume + Add AX, 64 + ShR AX, 7 + Mov [SI+0Ch], AX ; Store into right volume + + Mov AL, 64 + Sub AL, [SI+37h] + Mul Byte Ptr [SI+20h] + Add AX, 64 + ShR AX, 7 + Mov [SI+0Eh], AX ; Left volume + + Mov CH, AL ; CH = left volume + Mov CL, [SI+0Ch] ; CL = right volume + Mov AX, 0 + + Test CX, CX + JZ MixModeCommon + + Mov AL, 30 ; Left only... + Test CL, CL + JZ MixModeCommon + + Mov AL, 60 + Test CH, CH + JZ MixModeCommon + + Mov AL, 90 + Cmp CL, CH + JZ MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix0ModeSurround: + Mov AL, [SI+20h] + ShR AL, 2 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 150 ; Surround + Jmp MixModeCommon + +Mix6ModeMono: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 8 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Test AX, AX + JZ MixModeCommon + Mov AX, 30 + Jmp MixModeCommon + +Mix6ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix6ModeSurround + + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Ch], AX ; Store into right volume + Mov BX, AX + ShL EAX, 16 + + Mov AL, 64 ; Do left volume + Sub AL, [SI+37h] ; AL = 64-FinalPan + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Eh], AX + + Mov ECX, EAX + + ; BX = right volume + ; CX = Left volume + Mov AX, 0 + Test ECX, ECX + JZ MixModeCommon + + Mov AL, 30 + Test BX, BX + JZ MixModeCommon + + Mov AL, 60 + Test CX, CX + JZ MixModeCommon + + Mov AL, 90 + Cmp CX, BX + JE MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix6ModeSurround: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 9 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + JZ MixModeCommon + Mov AX, 150 + Jmp MixModeCommon + +MixModeCommon: ; Requires AX = 30/60/90 etc. depending + ; On mixing mode type. + ; This will add 180 for 16-bit, + ; And sort out loop types. + Mov BL, [SI+0Ah] + Test Byte Ptr [SI+18h], 2 ; 16 bit? + JZ MixModeCommon1 + + Add AX, 180 + +MixModeCommon1: + Cmp BL, 8 + JB MixModeCommon3 ; No loop + JE MixModeCommon2 ; Forwards loop + + Add AX, 10 + +MixModeCommon2: + Add AX, 10 + +MixModeCommon3: + Add AX, Offset MixFunctionTables + Add AX, MixModeOffset + Mov [SI+8], AX ; Offset... + +MixSamplesMix: + Mov BX, [SI+8] ; BX = offset into + Mov EAX, [CS:BX+2] + Mov DWord Ptr PreMixFunction, EAX + Mov EAX, [CS:BX+6] + Mov DWord Ptr MixFunctionSeparateBackwards, EAX + + Mov AX, BytesToMix + Mov MixBlockSize, AX + Mov MixBufferOffset, MIXTABLESIZE + + Mov EAX, CURRENTPOSITION + Mov OLDPOSITION, EAX + + Call Word Ptr [CS:BX] + + And Word Ptr [SI], 0111100010001101b + Jmp MixSamplesEnd + +MixSamplesHandleError: + Mov Word Ptr [SI], 200h + + Test Byte Ptr [SI+3Ah], 80h + JNZ MixSamplesEnd + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Turn off channel + +MixSamplesEnd: + Pop CX + +MixSamplesEnd2: + Add SI, 128 + Dec CX + JNZ MixSamples2 + + Ret + +EndP MixSamples + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include fourier.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc AckIRQ + Assume DS:Driver + + Mov AL, 20h + Cmp CS:IRQ, 7 + JBE AckIRQ1 + + Out 0A0h, AL + +AckIRQ1: + Out 20h, AL + Ret + +EndP AckIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc CheckMIDI + + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Xor BX, BX + Mov DX, MIDIPort + + Mov BL, [MIDIBufferTail] + Test DX, DX + JZ CheckMIDIEnd + + Inc DX + Mov CX, 0FFFFh + +CheckMIDIAgain: + In AL, DX + + Test AL, 80h + LoopNZ CheckMIDIAgain + + Dec DX + In AL, DX + + Cmp AL, 0F0h + JAE CheckMIDIEnd + + Inc BL + Cmp BL, MIDIBufferHead + JE CheckMIDIEnd + + Mov [MIDIBuffer+BX], AL + Mov [MIDIBufferTail], BL +; Jmp CheckMIDIAgain + +CheckMIDIEnd: + Pop DS + Ret + +EndP CheckMIDI + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SB16IRQHandler + + PushAD + Push DS + Push ES + + CLD + +SBIRQAgain: + Mov AX, CS + Mov DS, AX + Assume DS:Driver + + Mov DX, BasePort + Add DL, 4 ; Mixer Port + Mov AL, 82h + Out DX, AL + Inc DL ; DX = BasePort+5 + In AL, DX + + Test AL, 4 + JZ SBMIDIInterruptEnd + + Push AX + Call CheckMIDI + Pop AX + +SBMIDIInterruptEnd: + Test AL, 2 + JNZ SBDigitalInterrupt + + Call AckIRQ + Jmp SBIRQEnd + +SBDigitalInterrupt: + Mov DX, BasePort + Add DL, 0Fh + In AL, DX ; 16-bit IRQ ack. + + Call AckIRQ + +DMAPort1 EQU $+1 + In AL, 1 + Mov BL, AL +DMAPort2 EQU $+1 + In AL, 1 + Mov BH, AL + + Xor AX, AX + +DMA16BITADJUST EQU $ + ShL BX, 1 + + Cmp BX, DMABUFFERLENGTH/2 + JB SB16IRQHandler2 + + Mov AX, DMABUFFERLENGTH/2 + +SB16IRQHandler2: + ; OK... time to get next block + ; Check whether stereo thing is on.. + ; + LES DI, [ActualDMAPtr] + Add DI, AX + + Mov BX, DMASize ; BX = bytes required + ShR BX, 1 + ; BX = samples required + Mov BP, 8 ; Skip for mono + Mov CL, 14 ; Shift for mono + + Cmp Stereo, 0 + JE SB16IRQHandlerMono + + Mov BP, 4 ; Stereo skip value. + Dec CL + +SB16IRQHandlerMono: + Call SaveEMSPageFrame + + Cmp MixTransferRemaining, 0 + JNE SB16IRQHandler4 + Assume DS:Nothing + +SB16IRQHandler3: + Push BX + Push CX + Push BP + Push ES + Push DI + + Call Update + Call MixSamples + Call UpdateFourierBuffer + + Pop DI + Pop ES + Pop BP + Pop CX + Pop BX + +SB16IRQHandler4: + Mov DS, MixSegment + Mov SI, MixTransferOffset + Mov DX, BX ; DX = samples to transfer + Cmp DX, MixTransferRemaining + JBE SB16IRQHandler5 + + Mov DX, MixTransferRemaining + +SB16IRQHandler5: + Push DX + Cmp CS:Filter, 1 + JB SB16IRQHandler6 + JE SB16IRQHFilter + + Cmp CS:Stereo, 0 + JE SB16IRQ3QFilterMono + +SB16IRQ3QFilterStereo: + Push BX + + Mov EBX, FilterValue + Mov EBP, FilterValue2 + ShR DX, 1 + +SB16IRQ3QFilterStereo1: + Mov EAX, EBX + Mov ECX, EBP + Add EAX, [SI] + Add ECX, [SI+4] + SAR EAX, 1 + SAR ECX, 1 + Add EBX, EAX + Add EBP, ECX + SAR EBX, 1 + SAR EBP, 1 + + Mov EAX, EBX + SAR EAX, 13 + + Cmp EAX, -8000h + JL SB163QFilterStereoClip1 + Cmp EAX, 7FFFh + JG SB163QFilterStereoClip2 + +SB16IRQ3QFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL SB163QFilterStereoClip3 + Cmp EAX, 7FFFh + JG SB163QFilterStereoClip4 + +SB16IRQ3QFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ SB16IRQ3QFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp SB16MixTransferEnd + +SB16IRQ3QFilterMono: + Push BX + + Mov EBX, FilterValue + +SB16IRQ3QFilterMono1: + Mov EAX, EBX + Add EAX, [SI] + SAR EAX, 1 + Add EBX, EAX + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL SB163QFilterMonoClip1 + Cmp EAX, 7FFFh + JG SB163QFilterMonoClip2 + +SB16IRQ3QFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ SB16IRQ3QFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp SB16MixTransferEnd + +SB16IRQHFilter: + Cmp CS:Stereo, 0 + JE SB16IRQHFilterMono + +SB16IRQHFilterStereo: + Push BX + + Mov EBX, FilterValue + Mov EBP, FilterValue2 + ShR DX, 1 + +SB16IRQHFilterStereo1: + Add EBX, [SI] + Add EBP, [SI+4] + + SAR EBX, 1 + SAR EBP, 1 + + Mov EAX, EBX + SAR EAX, 13 + + Cmp EAX, -8000h + JL SB16HFilterStereoClip1 + Cmp EAX, 7FFFh + JG SB16HFilterStereoClip2 + +SB16IRQHFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL SB16HFilterStereoClip3 + Cmp EAX, 7FFFh + JG SB16HFilterStereoClip4 + +SB16IRQHFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ SB16IRQHFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp SB16MixTransferEnd + +SB16IRQHFilterMono: + Push BX + + Mov EBX, FilterValue + +SB16IRQHFilterMono1: + Add EBX, [SI] + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL SB16HFilterMonoClip1 + Cmp EAX, 7FFFh + JG SB16HFilterMonoClip2 + +SB16IRQHFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ SB16IRQHFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp SB16MixTransferEnd + +SB16IRQHandler6: + Mov EAX, [SI] + SAR EAX, CL + + Cmp EAX, -8000h + JL SB16IRQHandlerClip1 + Cmp EAX, 7FFFh + JG SB16IRQHandlerClip2 + +SB16IRQHandler7: + StosW ; } Memory write + + Add SI, BP + Dec DX + JNZ SB16IRQHandler6 + +SB16MixTransferEnd: + Pop DX + + Sub MixTransferRemaining, DX ; } Memory write + Sub BX, DX + JNZ SB16IRQHandler3 + + Mov MixTransferOffset, SI ; } Memory write + + Call RestoreEMSPageFrame + +SBIRQEnd: + + Pop ES + Pop DS + PopAD + IRet + +SB16IRQHandlerClip1: + Mov AX, 8000h + Jmp SB16IRQHandler7 + +SB16IRQHandlerClip2: + Mov AX, 7FFFh + Jmp SB16IRQHandler7 + +SB16HFilterMonoClip1: + Mov AX, 8000h + Jmp SB16IRQHFilterMono2 + +SB16HFilterMonoClip2: + Mov AX, 7FFFh + Jmp SB16IRQHFilterMono2 + +SB16HFilterStereoClip1: + Mov AX, 8000h + Jmp SB16IRQHFilterStereo2 + +SB16HFilterStereoClip2: + Mov AX, 7FFFh + Jmp SB16IRQHFilterStereo2 + +SB16HFilterStereoClip3: + Mov AX, 8000h + Jmp SB16IRQHFilterStereo3 + +SB16HFilterStereoClip4: + Mov AX, 7FFFh + Jmp SB16IRQHFilterStereo3 + +SB163QFilterMonoClip1: + Mov AX, 8000h + Jmp SB16IRQ3QFilterMono2 + +SB163QFilterMonoClip2: + Mov AX, 7FFFh + Jmp SB16IRQ3QFilterMono2 + +SB163QFilterStereoClip1: + Mov AX, 8000h + Jmp SB16IRQ3QFilterStereo2 + +SB163QFilterStereoClip2: + Mov AX, 7FFFh + Jmp SB16IRQ3QFilterStereo2 + +SB163QFilterStereoClip3: + Mov AX, 8000h + Jmp SB16IRQ3QFilterStereo3 + +SB163QFilterStereoClip4: + Mov AX, 7FFFh + Jmp SB16IRQ3QFilterStereo3 + +EndP SB16IRQHandler + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + + PushAD + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Add DI, Offset IRQData + Mov BX, [DI] + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset SB16IRQHandler + + XChg [ES:BX], EAX + Mov OldIRQHandler, EAX + + Mov AX, IMR + And AX, [DI+2] + + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Pop ES + Pop DS + PopAD + + Ret + +EndP SetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIRQ + + PushAD + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Mov BX, [IRQData+DI] + + Mov EAX, OldIRQHandler + Mov [ES:BX], EAX + + Pop ES + Pop DS + PopAD + + Ret + +EndP ResetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StartSB16 ; + + PushA + Push ES + + ; Setup DMA + Mov BX, DMASegment + Xor AX, AX + Mov DX, DMA + Mov DI, DMABUFFERLENGTH + Cmp DX, 3 + JA StartSB16B + + Mov Word Ptr [DMA16BITADJUST], 9090h + +StartSB16B: + Call SetDMA + + LES DI, ActualDMAPtr + Xor AX, AX + Mov CX, DMABUFFERLENGTH/2 + Rep StosW + + Mov MixTransferRemaining, 0 + + Mov DX, BasePort + Add DL, 0Ch + + Mov AL, 0D1h ; turn on speaker + Call SBOut + + Mov AL, 40h ; time constant + Call SBOut + Mov AL, SBMixConst + Call SBOut + + Mov AL, 0B6h ; 16 bit, DAC + Call SBOut + Mov AL, Stereo + ShL AL, 5 + Or AL, 10h + Call SBOut + + Mov AX, DMASize + ShR AX, 1 + Dec AX + + Call SBOut ; DMALength, Lo + Mov AL, AH + Call SBOut + + Pop ES + PopA + + Ret + + Assume DS:Nothing + +EndP StartSB16 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixerRegisters + + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Pop DS + + Ret + +EndP GetMixerRegisters + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + Mov SI, Offset RelocationTable + +RelocationFix: + LodsW + Test AX, AX + JZ RelocationEnd + Mov BX, AX + Mov [BX], DS + Jmp RelocationFix + +RelocationEnd: + Call GetEMSPageFrame + Mov EMSPageFrame, AX + + In AL, 0A1h + Mov AH, AL + In AL, 21h + Mov IMR, AX + + Mov DX, BasePort + Add DL, 4 + + Mov AL, 30h + Call SBGetRegister + ShR AL, 3 + Mov VolumeTable, AL + + Mov AL, 31h + Call SBGetRegister + ShR AL, 3 + Mov [VolumeTable+1], AL + + Mov AL, 44h + Call SBGetRegister + ShR AL, 4 + Mov [VolumeTable+2], AL + + Mov AL, 45h + Call SBGetRegister + ShR AL, 4 + Mov [VolumeTable+3], AL + + Mov AL, 46h + Call SBGetRegister + ShR AL, 4 + Mov [VolumeTable+4], AL + + Mov AL, 47h + Call SBGetRegister + ShR AL, 4 + Mov [VolumeTable+5], AL + + Call GetSBMixConst + + ; Parags to allocate = (8/(.4*31*16))*MixSpeed + 2080 + ; = .04032258*MixSpeed = (65536*.04032258*MixSpeed) / 65536 + + Mov AX, 2643 + Mul MixSpeed + Add AX, 0FFFFh + AdC DX, 2080 + + Mov BX, (DMABUFFERLENGTH*2)/16 + (FOURIERBUFFERLENGTH*2)/16 + Add BX, DX + + ; Allocate MixSegment first + Mov AH, 48h + + Int 21h + JNC InitSound1 + +InitSoundNoMemory: + Mov SI, Offset SB16NoMemoryMsg + Ret + +InitSound1: + Mov MixSegment, AX + Add AX, DX + Mov DMASegment, AX + Add AX, (DMABUFFERLENGTH*2)/16 + Mov FourierSegment, AX + Sub DX, 2080 + Mov MixSegmentLength, DX + + Call SetIRQ + Call GetTempo + Call SetTempo + + Mov DX, 330h + Call DetectUART + JC DetectMIDI1 + + Mov MIDIPort, 330h + Jmp DetectMIDIEnd + +DetectMIDI1: + Mov DX, 300h + Call DetectUART + JC DetectMIDIEnd + + Mov MIDIPort, 300h + +DetectMIDIEnd: + Mov SI, Offset SB16Msg + + Mov AX, BasePort + Mov BX, IRQ + Mov CX, DMA + + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, BasePort + Call ResetDSP + + Call ResetUART + Call ResetIRQ + + ; Delay.. + Mov DX, BasePort + Add DL, 0Ch + + Mov CX, 1000 +ReInitSound1: + In AL, DX + Loop ReInitSound1 + + Call SetIRQ + Call ReinitUART + + Mov SI, Offset ReInitMsg + Mov BX, 40 + Call SetInfoLine + + Mov AL, Stereo + Call SetStereo + + Pop ES + Pop DS + PopA + + Ret + +EndP ReInitSound + Assume DS:Nothing + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Mov DX, CS:BasePort + Add DL, 0Ch + + Mov AL, 0D9h + Call SBOut + + Call ResetUART + + Mov AX, BasePort + Call ResetDSP + + Call ResetDSPDMA + Call ResetDSPIRQ + + Mov AX, IMR + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Mov AX, MixSegment + Test AX, AX + JZ UnInitSound1 + + Mov ES, AX + Mov AH, 49h ; Release MixSegment + Int 21h + + Call ResetIRQ + +UnInitSound1: + Ret + +EndP UnInitSound + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + Push CS + Pop DS + Assume DS:Driver + +Poll1: + Call [UARTBufferEmpty] + JNC PollEnd + + Xor BX, BX + + ClI + + Mov BL, MIDIBufferHead + Cmp BL, MIDIBufferTail + JZ PollEnd ; Nothing in queue + + Inc BL + Mov AL, [MIDIBuffer+BX] + Mov MIDIBufferHead, BL + + Call [UARTSend] + Jmp Poll1 + +PollEnd: + StI + + Ret + +EndP Poll + Assume DS:Nothing + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Push AX + Push BX + Push DX + + Push BX + + Mov AX, MixSpeed + Mov BX, AX + Xor DX, DX + + ShL AX, 1 + RCL DX, 1 ; DX:AX = Mixspeed*2 + + ShR BX, 1 ; BX = Mixspeed/2 + + Add AX, BX + AdC DX, 0 ; DX:AX = Mixspeed*2.5 + + Pop BX ; BX = tempo + Div BX + + Mov BytesToMix, AX + + Pop DX + Pop BX + Pop AX + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + +; Mov CS:MixVolumeSet, AX + +; SetMixVolumeChain: + PushA + Push DS + +; Cmp CS:Surround, 0 +; JE SetMixVolumeSurround +; +; Mov BX, 49152 +; Mul BX +; Mov AX, DX +; +; SetMixVolumeSurround: + Mov BX, AX ; BX = MixVolume + Mov CS:MixVolume, AX + + Mov AX, CS:MixSegment + Test AX, AX + JZ SetMixVolume2 + + Mov DS, AX + + Mov CX, MIXTABLESIZE/2 + Mov SI, MIXTABLESIZE-2; Starting point - working backwards + +SetMixVolume1: + Mov AX, CX + + Dec AX ; AH = volume, AL = wave value. + Xor DX, DX + XChg AH, DL ; DL = Volume, AX = wave value + CBW + + IMul DX ; DX:AX = Volume * Wave Value + ; Ranges -8192->8128 + + IMul BX ; DX:AX = Volume * Wave Value * Mixing Volume + ; Ranges -1048576->1040384 + + Add AX, 64 + AdC DX, 0 + + ShRD AX, DX, 7 + Mov [SI], AX + Sub SI, 2 + + Dec CX + JNZ SetMixVolume1 + +SetMixVolume2: + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS: RecalculateAllVolumes + + Pop DS + PopA + + Ret + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Cmp CS:MixSegment, 0 + JE SetStereo1 + + Mov CS:Stereo, AL + Mov AX, CS:BasePort + Call ResetDSP + + Mov ES, CS:MixSegment + Mov CX, CS:MixSegmentLength + Mov DI, MIXTABLESIZE + ShL CX, 2 + Xor EAX, EAX + Rep StosD + + Call StartSB16 + +SetStereo1: + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include loadsam.inc + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset SB16ScreenList + + ClC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far ; Returns AX, given DI + + Xor AH, AH + Mov AL, [CS:VolumeTable+DI] + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far ; Given AX, DI + + Push DS + Push DX + + Push CS + Pop DS + Assume DS:Driver + + Mov [VolumeTable+DI], AL + + Mov DX, BasePort + Add DL, 4 + Mov AL, 30h + Mov AH, [VolumeTable] + ShL AH, 3 + Out DX, AX + + Mov AL, 31h + Mov AH, [VolumeTable+1] + ShL AH, 3 + Out DX, AX + + Mov AL, 44h + Mov AH, [VolumeTable+2] + ShL AH, 4 + Out DX, AX + + Mov AL, 45h + Mov AH, [VolumeTable+3] + ShL AH, 4 + Out DX, AX + + Mov AL, 46h + Mov AH, [VolumeTable+4] + ShL AH, 4 + Out DX, AX + + Mov AL, 47h + Mov AH, [VolumeTable+5] + ShL AH, 4 + Out DX, AX + + Pop DX + Pop DS + Ret + +EndP SetVariable + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetWaveForm Far ; Given ES:DI = destination + Assume DS:Nothing ; want 2048 samples. + + PushA + Push DS + + Mov DS, FourierSegment + Mov SI, FourierBufferStart + Mov CX, 2048 + +GetWaveForm1: + MovsW + And SI, (FOURIERBUFFERLENGTH*2)-1 + Loop GetWaveForm1 + + Pop DS + PopA + + Ret + +EndP GetWaveForm + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. + +StopAfterPlay DW 0 +DefaultChannels DW 64 +DriverFlags DW 4 + DW 4 Dup (0) + + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + DW 0 + DW Offset GetWaveform + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/SB16DRV.ASM b/SoundDrivers/SB16DRV.ASM new file mode 100755 index 0000000..f719fb2 --- /dev/null +++ b/SoundDrivers/SB16DRV.ASM @@ -0,0 +1,2672 @@ + + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;********************************** + +STEREOENABLED EQU 1 +DMABUFFERLENGTH EQU 8192 +MIXRESOLUTION EQU 32 ; 32 bit mixing for the SB16 +MIXTABLESIZE EQU 2*256*65 +FOURIERBUFFERLENGTH EQU 2048 + +SB16Msg DB "Sound Blaster 16 detected", 13 + DB "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, DMA ", 0FDh, "D", 0 + +SB16NoMemoryMsg DB "Sound Blaster 16 detected", 13 + DB "Error: Insufficient memory", 0 + +ReinitMsg DB "Sound Blaster 16 reinitialised", 0 + +ConfigErrorMsg DB "Error saving configuration to ITSB16.DRV", 0 +ConfigOKMsg DB "Configuration saved to ITSB16.DRV", 0 + +DriverName DB "ITSB16.DRV", 0 + +DSPVersion DW 0 +DSPIRQValue DB 0 +DSPDMAValue DB 0 +Forced DB 0 +Stereo DB 0 +MixVolume DW 0 +; MixVolumeSet DW 0 + +BytesToMix DW 1000 +SBMixConst DB 0 + +MixSegment DW 0 +DMASegment DW 0 +FourierSegment DW 0 +MixSegmentLength DW 0 + +MixTransferOffset DW 0 +MixTransferRemaining DW 0 + +CONFIGURATIONOFFSET EQU $+128 +CONFIGSIZE EQU 10 +MixMode DW 0 +MixModeOffset DW 0 +Filter DW 0 +Surround DW 0 +DMASize DW 2048 + +IMR DW 0 +OldIRQHandler DD 0 + +FilterValue DD 0 +FilterValue2 DD 0 + +MIDIPort DW 0 +MIDIBuffer DB 256 Dup (0) +MIDIBufferHead DB 0 +MIDIBufferTail DB 0 + +IRQData Label Word + DW 20h, 1111111111111110b ; IRQ 0 + DW 24h, 1111111111111101b ; IRQ 1 + DW 28h, 1111110111111011b ; IRQ 2 + DW 2Ch, 1111111111110111b ; IRQ 3 + DW 30h, 1111111111101111b ; IRQ 4 + DW 34h, 1111111111011111b ; IRQ 5 + DW 38h, 1111111110111111b ; IRQ 6 + DW 3Ch, 1111111101111111b ; IRQ 7 + DW 1C0h, 1111111011111011b ; IRQ 8 + DW 1C4h, 1111110111111011b ; IRQ 9 + DW 1C8h, 1111101111111011b ; IRQ 10 + DW 1CCh, 1111011111111011b ; IRQ 11 + DW 1D0h, 1110111111111011b ; IRQ 12 + DW 1D4h, 1101111111111011b ; IRQ 13 + DW 1D8h, 1011111111111011b ; IRQ 14 + DW 1DCh, 0111111111111011b ; IRQ 15 + + +;********************************** + +SB16ScreenList Label + DW 8 + DW Near Ptr IdleFunctionList + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr SB16HeaderLine + + DW Near Ptr VolumeText + DW Near Ptr VolumeBox1 + DW Near Ptr VolumeBox2 + + DW Near Ptr DriverText + + DW Near Ptr MasterVolumeLeft ; 8 + DW Near Ptr MasterVolumeRight ; 9 + DW Near Ptr TrebleVolumeLeft ; 10 + DW Near Ptr TrebleVolumeRight ; 11 + DW Near Ptr BassVolumeLeft ; 12 + DW Near Ptr BassVolumeRight ; 13 + + DW Near Ptr MixModeText + DW Near Ptr MixModeButton1 ; 15 + DW Near Ptr MixModeButton2 ; 16 + DW Near Ptr MixModeButton3 ; 17 + DW Near Ptr MixModeButton4 ; 18 + + DW Near Ptr FilterText + DW Near Ptr FilterButton1 ; 20 + DW Near Ptr FilterButton2 ; 21 + DW Near Ptr FilterButton3 ; 22 + + DW Near Ptr StereoText + DW Near Ptr StereoButton1 ; 24 + DW Near Ptr StereoButton2 ; 25 + DW Near Ptr StereoButton3 ; 25 + + DW Near Ptr FrequencyText + + DW 0 + + +SB16HeaderLine DW 10 + DB "Sound Blaster 16 Driver", 0 + +DriverText DW 1 + DB 31, 48 + DB 21h + DB "Sound Blaster 16 Driver 1.4 for Impulse Tracker", 0 + +VolumeText DW 1 + DB 2, 13 + DB 20h + DB "Master Volume Left", 13 + DB "Master Volume Right", 13 + DB 13 + DB 13 + DB "Treble Left", 13 + DB "Treble Right", 13 + DB "Bass Left", 13 + DB "Bass Right", 13 + DB 0 + +VolumeBox1 DW 0 + DB 21, 12, 27, 15 + DB 25 + +VolumeBox2 DW 0 + DB 14, 16, 18, 21 + DB 25 + +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +IdleFunctionList DD 0 + DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +MasterVolumeLeft DW 9 + DB 22, 13 + DW 0, 31 + DW 9, 0 + DW 0FFFFh, 9, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +MasterVolumeRight DW 9 + DB 22, 14 + DW 0, 31 + DW 9, 1 + DW 8, 10, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +TrebleVolumeLeft DW 9 + DB 15, 17 + DW 0, 15 + DW 9, 2 + DW 9, 11, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +TrebleVolumeRight DW 9 + DB 15, 18 + DW 0, 15 + DW 9, 3 + DW 10, 12, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +BassVolumeLeft DW 9 + DB 15, 19 + DW 0, 15 + DW 9, 4 + DW 11, 13, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +BassVolumeRight DW 9 + DB 15, 20 + DW 0, 15 + DW 9, 5 + DW 12, 15, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +MixModeText DW 1 + DB 2, 23 + DB 20h + DB "Mixing Mode", 0 + +FrequencyText DW 1 + DB 2, 48 + DB 20h + DB "Playback Frequency: ", 0FDh, "DHz", 0 +MixSpeed DW 45454 + +MixModeButton1 DW 2 + DW 13, 16, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment1 DW 0 + DW 0 + DW Offset SetMixMode +DriverSegment2 DW 0 + DB 3, 25, 32, 27, 8 + DB 0 + DB " 16 Bit, Non-Interpolated", 0 + +MixModeButton2 DW 2 + DW 15, 17, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment3 DW 0 + DW 2 + DW Offset SetMixMode +DriverSegment4 DW 0 + DB 3, 28, 32, 30, 8 + DB 0 + DB " 16 Bit, Interpolated", 0 + +MixModeButton3 DW 2 + DW 16, 18, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment5 DW 0 + DW 4 + DW Offset SetMixMode +DriverSegment6 DW 0 + DB 3, 31, 32, 33, 8 + DB 0 + DB " 32 Bit, Non-Interpolated", 0 + +MixModeButton4 DW 2 + DW 17, 20, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment7 DW 0 + DW 6 + DW Offset SetMixMode +DriverSegment8 DW 0 + DB 3, 34, 32, 36, 8 + DB 0 + DB " 32 Bit, Interpolated", 0 + +FilterText DW 1 + DB 40, 13 + DB 20h + DB "Filter mode", 0 + +FilterButton1 DW 2 + DW 18, 21, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment9 DW 0 + DW 0 + DW Offset SetFilter +DriverSegment10 DW 0 + DB 42, 15, 60, 17, 8 + DB 0 + DB " No Filter", 0 + +FilterButton2 DW 2 + DW 20, 22, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment11 DW 0 + DW 1 + DW Offset SetFilter +DriverSegment12 DW 0 + DB 42, 18, 60, 20, 8 + DB 0 + DB " 50% Filter", 0 + +FilterButton3 DW 2 + DW 21, 24, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment13 DW 0 + DW 2 + DW Offset SetFilter +DriverSegment14 DW 0 + DB 42, 21, 60, 23, 8 + DB 0 + DB " 75% Filter", 0 + +StereoText DW 1 + DB 40, 25 + DB 20h + DB "Feedback mode", 0 + +StereoButton1 DW 2 + DW 22, 25, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetSurround +DriverSegment15 DW 0 + DW 0 + DW Offset SetSurround +DriverSegment16 DW 0 + DB 42, 27, 60, 29, 8 + DB 0 + DB " None", 0 + +StereoButton2 DW 2 + DW 24, 26, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetSurround +DriverSegment17 DW 0 + DW 1 + DW Offset SetSurround +DriverSegment18 DW 0 + DB 42, 30, 60, 32, 8 + DB 0 + DB " 50% Separated", 0 + +StereoButton3 DW 2 + DW 25, 0FFFFh, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetSurround +DriverSegment19 DW 0 + DW 2 + DW Offset SetSurround +DriverSegment20 DW 0 + DB 42, 33, 60, 35, 8 + DB 0 + DB " 50% Crossed", 0 + + +VolumeTable DB 6 Dup (0) + +; ÄÄ MixingRoutines ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixBufferPos DW 0 + +include dma.inc +include mix.inc +include m12bit.mix +include m12biti.mix +include m32bit.mix +include m32biti.mix + +MixFunctionTables Label + +include m12bit.inc ; contains the tables +include m12biti.inc +include m32bit.inc +include m32biti.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +RelocationTable Label Word + DW Offset DriverSegment1, Offset DriverSegment2 + DW Offset DriverSegment3, Offset DriverSegment4 + DW Offset DriverSegment5, Offset DriverSegment6 + DW Offset DriverSegment7, Offset DriverSegment8 + DW Offset DriverSegment9, Offset DriverSegment10 + DW Offset DriverSegment11, Offset DriverSegment12 + DW Offset DriverSegment13, Offset DriverSegment14 + DW Offset DriverSegment15, Offset DriverSegment16 + DW Offset DriverSegment17, Offset DriverSegment18 + DW Offset DriverSegment19, Offset DriverSegment20 + DW 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SBOut ; AL = data + ; DX = 2xCh + + Push AX + +SBOut1: + In AL, DX + Test AL, AL + JS SBOut1 + + Pop AX + Out DX, AL + + Ret + +EndP SBOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SBIn ; DX = 2xEh, returns AL + +SBIn1: + In AL, DX + Test AL, AL + JNS SBIn1 + + Add DL, 0Ah-0Eh ; DX = 2xAh -> Data read port + In AL, DX + Add DL, 0Eh-0Ah + + Ret + +EndP SBIn + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectUART ; Given DX = Port + +; From SB-DevKit + + ClI + + Inc DX + Xor CX, CX + +DetectUART1: + In AL, DX + Test AL, 40h ; Ready for output + LoopNZ DetectUART1 + JNZ DetectUARTError + + Mov AL, 0FFh ; Reset! + Out DX, AL + + Xor CX, CX + +DetectUART2: + In AL, DX + Test AL, 80h + JNZ DetectUART3 + + Dec DX + In AL, DX + Inc DX + Cmp AL, 0FEh + JE DetectUART4 + +DetectUART3: + Loop DetectUART2 + +DetectUARTError: + StI + StC + Ret + +DetectUART4: ; Now to shove it into 'intelligent' mode. + Xor CX, CX + +DetectUART5: + In AL, DX + Test AL, 40h + LoopNZ DetectUART5 + JNZ DetectUARTError + + Mov AL, 3Fh ; Intelligent mode! + Out DX, AL + +DetectUART6: + Xor CX, CX + +DetectUART7: + In AL, DX + Test AL, 80h + JNZ DetectUART8 + + Dec DX + In AL, DX + Inc DX + Cmp AL, 0FEh + JE DetectUART9 + +DetectUART8: + Loop DetectUART7 + + Jmp DetectUARTError + +DetectUART9: + StI + ClC + Ret + +EndP DetectUART + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReinitUART + + Mov DX, MIDIPort + Test DX, DX + JZ ReinitUART1 + + Call DetectUART + +ReinitUART1: + Ret + +EndP ReinitUART + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetUART + + Mov DX, MIDIPort + Test DX, DX + JZ ResetUART1 + + Inc DX + + Mov AL, 0FFh + Out DX, AL + +ResetUART1: + Ret + +EndP ResetUART + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixMode Far + + Push CS + Pop ES + Mov DI, Offset MixMode + + Ret + +EndP GetMixMode + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetFilter Far + + Push CS + Pop ES + Mov DI, Offset Filter + + Ret + +EndP GetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetFilter Far + + Mov AX, [SI+22] + Mov CS:FilterValue, 0 + Mov CS:Filter, AX + Jmp SetMixModeChain + +EndP SetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetSurround Far + + Push CS + Pop ES + Mov DI, Offset Surround + + Ret + +EndP GetSurround + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetSurround Far + + Mov AX, [SI+22] + Mov CS:Surround, AX + +; Mov AX, CS:MixVolumeSet +; Call Far Ptr SetMixVolumeChain + + Jmp SetMixModeChain + +EndP SetSurround + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixMode Far + + Mov AX, [SI+22] + + ClI + + Mov CS:MixMode, AX + + Mov BX, 180 + Mul BX + Mov CS:MixModeOffset, AX + + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS:RecalculateAllVolumes + + StI + +SetMixModeChain: + Call GotoHomeDirectory + + ; Now to save config into driver file. + Push CS + Pop DS + Assume DS:Driver + + Mov AX, 3D02h ; Read write access + Mov DX, Offset DriverName + Mov SI, Offset ConfigErrorMsg + Int 21h + JC SetMixMode1 + + Mov BX, AX + + Mov AX, 4200h + Xor CX, CX + Mov DX, Offset CONFIGURATIONOFFSET + Int 21h + JC SetMixMode2 + + Mov AH, 40h + Mov CX, CONFIGSIZE + Mov DX, Offset MixMode + Int 21h + +SetMixMode2: + PushF + Mov AH, 3Eh + Int 21h + PopF + + JC SetMixMode1 + + Mov SI, Offset ConfigOKMsg + +SetMixMode1: + Mov BX, 40 + Call SetInfoLine + + Mov AX, 1 + Ret + +EndP SetMixMode + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SBGetRegister + + Out DX, AL + Inc DX + In AL, DX + Dec DX + + Ret + +EndP SBGetRegister + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetSBMixConst ; Work out value.. and nearest + ; mixspeed value. + + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, CmdLineMixSpeed + Mov CX, MixSpeed + Test AX, AX + JZ GetSBMixConst1 + + Mov CX, 45454 + Cmp AX, CX + JA GetSBMixConst1 + + Mov CX, 12000 + Cmp AX, CX + JB GetSBMixConst1 + + Mov CX, AX + +GetSBMixConst1: + Mov AX, 1000 + Mul AX + Div CX + Mov AH, AL + Neg AH + Mov SBMixConst, AH + + MovZX BX, AL + Mov AX, 1000 + Mul AX + Div BX + Mov MixSpeed, AX + + Mov BX, 12000 + Xor DX, DX + Div BX + Mov FourierBufferStepOffset, AX + Mov FourierBufferStepFractional, DX + + Pop DS + PopA + Ret + +EndP GetSBMixConst + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetDSP Far ; AX = Port + + Push AX + Push CX + Push DX + + Mov DX, AX + Add DL, 6 + Mov AL, 1 + Out DX, AL + + In AL, DX + In AL, DX + In AL, DX + In AL, DX + + Xor AL, AL + Out DX, AL + + Add DL, 8 + Mov CX, 200 + +ResetDSP1: + In AL, DX + Test AL, AL + JS ResetDSP2 + Loop ResetDSP1 + Jmp ResetDSP3 + +ResetDSP2: + Sub DL, 4 + In AL, DX + Cmp AL, 0AAh + JE ResetDSP4 + Add DL, 4 + Loop ResetDSP1 + +ResetDSP3: + StC + +ResetDSP4: + Pop DX + Pop CX + Pop AX + Ret + +EndP ResetDSP + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetDSPIRQ + + Mov DX, CS:BasePort + Add DL, 4 + Mov AH, CS:DSPIRQValue + Mov AL, 80h + Out DX, AX + + Ret + +EndP ResetDSPIRQ + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetDSPDMA + + Mov DX, CS:BasePort + Add DL, 4 + Mov AH, CS:DSPDMAValue + Mov AL, 81h + Out DX, AX + + Ret + +EndP ResetDSPDMA + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far + + Push CS + Pop DS + Assume DS:Driver + + Mov Forced, AL + + Mov AX, BasePort + Cmp AX, 0FFFFh + JE DetectCard1 + + Cmp AX, 210h + JB DetectCard9 + Cmp AX, 280h + JA DetectCard9 + + Call ResetDSP + JNC DetectCard2 + + Ret + +DetectCard1: + Mov AX, 210h + +DetectCard2: + Call ResetDSP + JNC DetectCard3 + Add AL, 10h + Cmp AL, 80h + JBE DetectCard2 + +DetectCard9: + StC + Ret + +DetectCard3: ; OK... DSP found. + ; Get DSP version + Mov BasePort, AX + + Mov DX, AX + Add DL, 0Ch ; 2xCh -> Data ready to send... + +DetectCardOuputLoop1: + In AL, DX + Test AL, AL + JS DetectCardOuputLoop1 + + Mov AL, 0E1h ; Get DSP version command + Out DX, AL + + Add DL, 0Eh-0Ch ; DX = 2xEh -> Data available status + + Call SBIn + Mov AH, AL ; AH = Major version number + Call SBIn ; AL = Minor version number + + Cmp AH, 4 ; SB DSP = 4.00+ + JAE DetectCard5 + +DetectCard4: + StC + Ret + +DetectCard5: + Mov DSPVersion, AX + + Add DL, 04h-0Eh ; 2x4h = Mixer index port + Mov AL, 80h ; IRQ select + Out DX, AL + Inc DL ; 2x5h = Mixer data port + + In AL, DX + + Dec DL + + Mov DSPIRQValue, AL + ; OK.. now get IRQ, or set IRQ + Mov BX, IRQ + Cmp BX, 0FFFFh + JE DetectCardIRQ1 + Cmp Forced, 0 + JE DetectCardIRQ1 + + Mov AH, 11h + Cmp BL, 2 + JE SetCardIRQ1 + Cmp BL, 9 + JE SetCardIRQ1 + + Mov AH, 12h + Cmp BL, 5 + JE SetCardIRQ1 + + Mov AH, 14h + Cmp BL, 7 + JE SetCardIRQ1 + + Mov AH, 18h + Cmp BL, 10 + JE SetCardIRQ1 + + StC + Ret + +SetCardIRQ1: + Mov AL, 80h + Out DX, AL + Inc DL + Mov AL, AH + Out DX, AL + Dec DL + Jmp DetectCard6 + +DetectCardIRQ1: + Mov BX, 2 + Test AL, 1 + JNZ DetectCardIRQ2 + + Mov BL, 5 + Test AL, 2 + JNZ DetectCardIRQ2 + + Mov BL, 7 + Test AL, 4 + JNZ DetectCardIRQ2 + + Mov BL, 10 + Test AL, 8 + JNZ DetectCardIRQ2 + + StC + Ret + +DetectCardIRQ2: + Cmp IRQ, 0FFFFh + JE DetectCardIRQ3 + + Cmp BX, IRQ + JE DetectCard6 + + StC + Ret + +DetectCardIRQ3: + Mov IRQ, BX + +DetectCard6: ; Detect DMA + Mov AL, 81h ; DMA select + Out DX, AL + Inc DL + In AL, DX ; AL = DMA + Dec DL + + Mov DSPDMAValue, AL + + Mov BX, DMA + Cmp BX, 0FFFFh + JE DetectCardDMA1 + Cmp Forced, 0 + JE DetectCardDMA1 + + Mov CL, 1 + Cmp BX, 1 + JB SetCardDMA1 + + Mov CL, 2 + JE SetCardDMA1 + + Cmp BX, 3 + JB DetectCard7 + + Mov CL, 8 + JE DetectCard7 + + Mov CL, 20h + Cmp BX, 5 + JB DetectCard7 + JE SetCardDMA1 + + Mov CL, 80h + Cmp BX, 7 + JA DetectCard7 + JE SetCardDMA1 + + Mov CL, 40h + +SetCardDMA1: + And AL, 0Bh + Test CL, 0Bh + JZ SetCardDMA4 + + Xor AL, AL + +SetCardDMA4: + Or CL, AL + + Mov AL, 81h + Out DX, AL + Inc DL + Mov AL, CL + Out DX, AL + Jmp DetectCard7 + +DetectCardDMA1: + Mov BX, 5 + Test AL, 20h + JNZ DetectCardDMA2 + + Inc BL + Test AL, 40h + JNZ DetectCardDMA2 + + Inc BL + Test AL, 80h + JNZ DetectCardDMA2 + + Mov BL, 0 + Test AL, 1 + JNZ DetectCardDMA2 + + Inc BL + Test AL, 2 + JNZ DetectCardDMA2 + + Add BL, 2 + Test AL, 8 + JNZ DetectCardDMA2 + +DetectCard8: + Call ResetDSPIRQ + StC + Ret + +DetectCardDMA2: + Cmp DMA, 0FFFFh + JE DetectCardDMA3 + + Cmp BX, DMA + JNE DetectCard8 + +DetectCardDMA3: + Mov DMA, BX + +DetectCard7: + Mov EAX, 'Jeff' + + ClC + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixModeTable Label Word + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + +Proc MixSamples ; Given DS:SI = info tables, CX = numchannels + + ; 1. Clean buffer + ; + update variables + ; 2. Update parameters + ; 3. Mix func + ; 4. Return + + Push CX + + Mov CX, BytesToMix + Mov ES, MixSegment + Mov DI, MIXTABLESIZE + Mov DX, CX + Add CX, CX + + Mov MixTransferOffset, DI ; } Memory write + + Cmp Stereo, 0 + JE MixSamples1 + + Mov DX, CX + + Cmp Surround, 1 + JB MixSamplesCont + + Push DS + + Push ES + Pop DS + + JE MixSurround3 + +Surround1: + Mov EAX, [DI+4] + Mov EBX, [DI] + SAR EAX, 1 + SAR EBX, 1 + Mov [DI], EAX + Mov [DI+4], EBX + + Add DI, 8 + Sub CX, 2 + JNZ Surround1 + + Pop DS + Jmp SurroundCont + +MixSamples1: + Cmp Surround, 1 + JB MixSamplesCont + +MixSurround2: + Push DS + + Push ES + Pop DS + +MixSurround3: + SAR DWord Ptr [DI], 1 + Add DI, 4 + Dec CX + JNZ MixSurround3 + + Pop DS + Jmp SurroundCont + +MixSamplesCont: + Xor EAX, EAX + Rep StosD ; } Memory write + +SurroundCont: + Mov MixTransferRemaining, DX ; } + + Pop CX + +MixSamples2: + Test Byte Ptr [SI], 1 + JZ MixSamplesEnd2 + Cmp Byte Ptr [SI+36h], 100 + JE MixSamplesEnd2 + + Push CX + Mov CX, [SI] + + Test CH, 2 + JZ MixSamples3 + And Byte Ptr [SI], Not 1 + + Jmp MixSamplesEnd +; Cmp MixMode, 8 ; Is it volume ramping? +; JB MixSamplesEnd + +MixSamples3: + Test CL, 20h ; New freq? + JZ MixSamples5 + + Mov AX, [SI+10h] + Mov DX, [SI+12h] + Mov BX, MixSpeed + Cmp DX, BX + JAE MixSamplesHandleError + + Div BX + ShL EAX, 16 + Xor AX, AX + Div BX + Mov STEPVALUE, EAX + +MixSamples4: + Test CH, 1 + JZ MixSamples5 + + Mov DWord Ptr [SI+1Ch], 0 ; Current Volume = 0 + ; for volume sliding. +MixSamples5: + Test CX, 8440h ; New volume or panning? + JZ MixSamplesMix + + Xor AX, AX + Test CH, 8 ; Muted? + JNZ MixModeCommon + + Mov BX, MixMode + Add BL, Stereo + Add BX, BX + Jmp [CS:MixModeTable+BX] + +Mix0Mode: ; 16-bit mixing, no interpolation +Mix0ModeMono: ; and 16-bit mixing, interpolation + Mov AL, [SI+20h] + ShR AL, 1 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 30 ; Use left only-mixing for mono + Jmp MixModeCommon + +Mix0ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix0ModeSurround + + Mul Byte Ptr [SI+20h] ; Final volume + Add AX, 64 + ShR AX, 7 + Mov [SI+0Ch], AX ; Store into right volume + + Mov AL, 64 + Sub AL, [SI+37h] + Mul Byte Ptr [SI+20h] + Add AX, 64 + ShR AX, 7 + Mov [SI+0Eh], AX ; Left volume + + Mov CH, AL ; CH = left volume + Mov CL, [SI+0Ch] ; CL = right volume + Mov AX, 0 + + Test CX, CX + JZ MixModeCommon + + Mov AL, 30 ; Left only... + Test CL, CL + JZ MixModeCommon + + Mov AL, 60 + Test CH, CH + JZ MixModeCommon + + Mov AL, 90 + Cmp CL, CH + JZ MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix0ModeSurround: + Mov AL, [SI+20h] + ShR AL, 2 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 150 ; Surround + Jmp MixModeCommon + +Mix6ModeMono: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 8 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Test AX, AX + JZ MixModeCommon + Mov AX, 30 + Jmp MixModeCommon + +Mix6ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix6ModeSurround + + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Ch], AX ; Store into right volume + Mov BX, AX + ShL EAX, 16 + + Mov AL, 64 ; Do left volume + Sub AL, [SI+37h] ; AL = 64-FinalPan + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Eh], AX + + Mov ECX, EAX + + ; BX = right volume + ; CX = Left volume + Mov AX, 0 + Test ECX, ECX + JZ MixModeCommon + + Mov AL, 30 + Test BX, BX + JZ MixModeCommon + + Mov AL, 60 + Test CX, CX + JZ MixModeCommon + + Mov AL, 90 + Cmp CX, BX + JE MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix6ModeSurround: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 9 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + JZ MixModeCommon + Mov AX, 150 + Jmp MixModeCommon + +MixModeCommon: ; Requires AX = 30/60/90 etc. depending + ; On mixing mode type. + ; This will add 180 for 16-bit, + ; And sort out loop types. + Mov BL, [SI+0Ah] + Test Byte Ptr [SI+18h], 2 ; 16 bit? + JZ MixModeCommon1 + + Add AX, 180 + +MixModeCommon1: + Cmp BL, 8 + JB MixModeCommon3 ; No loop + JE MixModeCommon2 ; Forwards loop + + Add AX, 10 + +MixModeCommon2: + Add AX, 10 + +MixModeCommon3: + Add AX, Offset MixFunctionTables + Add AX, MixModeOffset + Mov [SI+8], AX ; Offset... + +MixSamplesMix: + Mov BX, [SI+8] ; BX = offset into + Mov EAX, [CS:BX+2] + Mov DWord Ptr PreMixFunction, EAX + Mov EAX, [CS:BX+6] + Mov DWord Ptr MixFunctionSeparateBackwards, EAX + + Mov AX, BytesToMix + Mov MixBlockSize, AX + Mov MixBufferOffset, MIXTABLESIZE + + Mov EAX, CURRENTPOSITION + Mov OLDPOSITION, EAX + + Call Word Ptr [CS:BX] + + And Word Ptr [SI], 0111100010001101b + Jmp MixSamplesEnd + +MixSamplesHandleError: + Mov Word Ptr [SI], 200h + + Test Byte Ptr [SI+3Ah], 80h + JNZ MixSamplesEnd + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Turn off channel + +MixSamplesEnd: + Pop CX + +MixSamplesEnd2: + Add SI, 128 + Dec CX + JNZ MixSamples2 + + Ret + +EndP MixSamples + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include fourier.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc AckIRQ + Assume DS:Driver + + Mov AL, 20h + Cmp CS:IRQ, 7 + JBE AckIRQ1 + + Out 0A0h, AL + +AckIRQ1: + Out 20h, AL + Ret + +EndP AckIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc CheckMIDI + + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Xor BX, BX + Mov DX, MIDIPort + + Mov BL, [MIDIBufferTail] + Test DX, DX + JZ CheckMIDIEnd + + Inc DX + Mov CX, 0FFFFh + +CheckMIDIAgain: + In AL, DX + + Test AL, 80h + LoopNZ CheckMIDIAgain + + Dec DX + In AL, DX + + Cmp AL, 0F0h + JAE CheckMIDIEnd + + Inc BL + Cmp BL, MIDIBufferHead + JE CheckMIDIEnd + + Mov [MIDIBuffer+BX], AL + Mov [MIDIBufferTail], BL +; Jmp CheckMIDIAgain + +CheckMIDIEnd: + Pop DS + Ret + +EndP CheckMIDI + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SB16IRQHandler + + PushAD + Push DS + Push ES + + CLD + +SBIRQAgain: + Mov AX, CS + Mov DS, AX + Assume DS:Driver + + Mov DX, BasePort + Add DL, 4 ; Mixer Port + Mov AL, 82h + Out DX, AL + Inc DL ; DX = BasePort+5 + In AL, DX + +Comment ~ + Test AL, 1 + JZ SB8BitDigitalInterruptEnd + +SB8BitDigitalInterrupt: + Push AX + Add DL, 0Eh-5 + In AL, DX + Pop AX + +SB8BitDigitalInterruptEnd: + + ~ + + Test AL, 4 + JZ SBMIDIInterruptEnd + + Push AX + Call CheckMIDI + Pop AX + +SBMIDIInterruptEnd: + Test AL, 2 + JNZ SBDigitalInterrupt + + Call AckIRQ + Jmp SBIRQEnd + +SBDigitalInterrupt: + Mov DX, BasePort + Add DL, 0Fh + In AL, DX ; 16-bit IRQ ack. + + Call AckIRQ + + Mov AX, MixBufferPos + Mov BX, AX + Mul DMASize + Cmp AX, DMABUFFERLENGTH + JB SB16IRQHandler2 + + Xor AX, AX + Xor BX, BX + +SB16IRQHandler2: + Inc BX + Mov MixBufferPos, BX + + + ; OK... time to get next block + ; Check whether stereo thing is on.. + ; + LES DI, [ActualDMAPtr] + Add DI, AX + + Mov BX, DMASize ; BX = bytes required + ShR BX, 1 + ; BX = samples required + Mov BP, 8 ; Skip for mono + Mov CL, 14 ; Shift for mono + + Cmp Stereo, 0 + JE SB16IRQHandlerMono + + Mov BP, 4 ; Stereo skip value. + Dec CL + +SB16IRQHandlerMono: + Call SaveEMSPageFrame + + Cmp MixTransferRemaining, 0 + JNE SB16IRQHandler4 + Assume DS:Nothing + +SB16IRQHandler3: + Push BX + Push CX + Push BP + Push ES + Push DI + + Call Update + Call MixSamples + Call UpdateFourierBuffer + + Pop DI + Pop ES + Pop BP + Pop CX + Pop BX + +SB16IRQHandler4: + Mov DS, MixSegment + Mov SI, MixTransferOffset + Mov DX, BX ; DX = samples to transfer + Cmp DX, MixTransferRemaining + JBE SB16IRQHandler5 + + Mov DX, MixTransferRemaining + +SB16IRQHandler5: + Push DX + Cmp CS:Filter, 1 + JB SB16IRQHandler6 + JE SB16IRQHFilter + + Cmp CS:Stereo, 0 + JE SB16IRQ3QFilterMono + +SB16IRQ3QFilterStereo: + Push BX + + Mov EBX, FilterValue + Mov EBP, FilterValue2 + ShR DX, 1 + +SB16IRQ3QFilterStereo1: + Mov EAX, EBX + Mov ECX, EBP + Add EAX, [SI] + Add ECX, [SI+4] + SAR EAX, 1 + SAR ECX, 1 + Add EBX, EAX + Add EBP, ECX + SAR EBX, 1 + SAR EBP, 1 + + Mov EAX, EBX + SAR EAX, 13 + + Cmp EAX, -8000h + JL SB163QFilterStereoClip1 + Cmp EAX, 7FFFh + JG SB163QFilterStereoClip2 + +SB16IRQ3QFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL SB163QFilterStereoClip3 + Cmp EAX, 7FFFh + JG SB163QFilterStereoClip4 + +SB16IRQ3QFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ SB16IRQ3QFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp SB16MixTransferEnd + +SB16IRQ3QFilterMono: + Push BX + + Mov EBX, FilterValue + +SB16IRQ3QFilterMono1: + Mov EAX, EBX + Add EAX, [SI] + SAR EAX, 1 + Add EBX, EAX + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL SB163QFilterMonoClip1 + Cmp EAX, 7FFFh + JG SB163QFilterMonoClip2 + +SB16IRQ3QFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ SB16IRQ3QFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp SB16MixTransferEnd + +SB16IRQHFilter: + Cmp CS:Stereo, 0 + JE SB16IRQHFilterMono + +SB16IRQHFilterStereo: + Push BX + + Mov EBX, FilterValue + Mov EBP, FilterValue2 + ShR DX, 1 + +SB16IRQHFilterStereo1: + Add EBX, [SI] + Add EBP, [SI+4] + + SAR EBX, 1 + SAR EBP, 1 + + Mov EAX, EBX + SAR EAX, 13 + + Cmp EAX, -8000h + JL SB16HFilterStereoClip1 + Cmp EAX, 7FFFh + JG SB16HFilterStereoClip2 + +SB16IRQHFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL SB16HFilterStereoClip3 + Cmp EAX, 7FFFh + JG SB16HFilterStereoClip4 + +SB16IRQHFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ SB16IRQHFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp SB16MixTransferEnd + +SB16IRQHFilterMono: + Push BX + + Mov EBX, FilterValue + +SB16IRQHFilterMono1: + Add EBX, [SI] + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL SB16HFilterMonoClip1 + Cmp EAX, 7FFFh + JG SB16HFilterMonoClip2 + +SB16IRQHFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ SB16IRQHFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp SB16MixTransferEnd + +SB16IRQHandler6: + Mov EAX, [SI] + SAR EAX, CL + + Cmp EAX, -8000h + JL SB16IRQHandlerClip1 + Cmp EAX, 7FFFh + JG SB16IRQHandlerClip2 + +SB16IRQHandler7: + StosW ; } Memory write + + Add SI, BP + Dec DX + JNZ SB16IRQHandler6 + +SB16MixTransferEnd: + Pop DX + + Sub MixTransferRemaining, DX ; } Memory write + Sub BX, DX + JNZ SB16IRQHandler3 + + Mov MixTransferOffset, SI ; } Memory write + + Call RestoreEMSPageFrame + +SBIRQEnd: + + Pop ES + Pop DS + PopAD + IRet + +SB16IRQHandlerClip1: + Mov AX, 8000h + Jmp SB16IRQHandler7 + +SB16IRQHandlerClip2: + Mov AX, 7FFFh + Jmp SB16IRQHandler7 + +SB16HFilterMonoClip1: + Mov AX, 8000h + Jmp SB16IRQHFilterMono2 + +SB16HFilterMonoClip2: + Mov AX, 7FFFh + Jmp SB16IRQHFilterMono2 + +SB16HFilterStereoClip1: + Mov AX, 8000h + Jmp SB16IRQHFilterStereo2 + +SB16HFilterStereoClip2: + Mov AX, 7FFFh + Jmp SB16IRQHFilterStereo2 + +SB16HFilterStereoClip3: + Mov AX, 8000h + Jmp SB16IRQHFilterStereo3 + +SB16HFilterStereoClip4: + Mov AX, 7FFFh + Jmp SB16IRQHFilterStereo3 + +SB163QFilterMonoClip1: + Mov AX, 8000h + Jmp SB16IRQ3QFilterMono2 + +SB163QFilterMonoClip2: + Mov AX, 7FFFh + Jmp SB16IRQ3QFilterMono2 + +SB163QFilterStereoClip1: + Mov AX, 8000h + Jmp SB16IRQ3QFilterStereo2 + +SB163QFilterStereoClip2: + Mov AX, 7FFFh + Jmp SB16IRQ3QFilterStereo2 + +SB163QFilterStereoClip3: + Mov AX, 8000h + Jmp SB16IRQ3QFilterStereo3 + +SB163QFilterStereoClip4: + Mov AX, 7FFFh + Jmp SB16IRQ3QFilterStereo3 + +EndP SB16IRQHandler + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + + PushAD + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Add DI, Offset IRQData + Mov BX, [DI] + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset SB16IRQHandler + + XChg [ES:BX], EAX + Mov OldIRQHandler, EAX + + Mov AX, IMR + And AX, [DI+2] + + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Pop ES + Pop DS + PopAD + + Ret + +EndP SetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIRQ + + PushAD + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Mov BX, [IRQData+DI] + + Mov EAX, OldIRQHandler + Mov [ES:BX], EAX + + Pop ES + Pop DS + PopAD + + Ret + +EndP ResetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StartSB16 ; + + PushA + Push ES + + ; Setup DMA + Mov BX, DMASegment + Xor AX, AX + Mov DX, DMA + Mov DI, DMABUFFERLENGTH + Call SetDMA + + LES DI, ActualDMAPtr + Xor AX, AX + Mov CX, DMABUFFERLENGTH/2 + Rep StosW + + Mov MixBufferPos, 0 + Mov MixTransferRemaining, 0 + + Mov DX, BasePort + Add DL, 0Ch + + Mov AL, 0D1h ; turn on speaker + Call SBOut + + Mov AL, 40h ; time constant + Call SBOut + Mov AL, SBMixConst + Call SBOut + + Mov AL, 0B6h ; 16 bit, DAC + Call SBOut + Mov AL, Stereo + ShL AL, 5 + Or AL, 10h + Call SBOut + + Mov AX, DMASize + ShR AX, 1 + Dec AX + + Call SBOut ; DMALength, Lo + Mov AL, AH + Call SBOut + + Pop ES + PopA + + Ret + + Assume DS:Nothing + +EndP StartSB16 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixerRegisters + + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Pop DS + + Ret + +EndP GetMixerRegisters + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + Mov SI, Offset RelocationTable + +RelocationFix: + LodsW + Test AX, AX + JZ RelocationEnd + Mov BX, AX + Mov [BX], DS + Jmp RelocationFix + +RelocationEnd: + Call GetEMSPageFrame + Mov EMSPageFrame, AX + + In AL, 0A1h + Mov AH, AL + In AL, 21h + Mov IMR, AX + + Mov DX, BasePort + Add DL, 4 + + Mov AL, 30h + Call SBGetRegister + ShR AL, 3 + Mov VolumeTable, AL + + Mov AL, 31h + Call SBGetRegister + ShR AL, 3 + Mov [VolumeTable+1], AL + + Mov AL, 44h + Call SBGetRegister + ShR AL, 4 + Mov [VolumeTable+2], AL + + Mov AL, 45h + Call SBGetRegister + ShR AL, 4 + Mov [VolumeTable+3], AL + + Mov AL, 46h + Call SBGetRegister + ShR AL, 4 + Mov [VolumeTable+4], AL + + Mov AL, 47h + Call SBGetRegister + ShR AL, 4 + Mov [VolumeTable+5], AL + + Call GetSBMixConst + + ; Parags to allocate = (8/(.4*31*16))*MixSpeed + 2080 + ; = .04032258*MixSpeed = (65536*.04032258*MixSpeed) / 65536 + + Mov AX, 2643 + Mul MixSpeed + Add AX, 0FFFFh + AdC DX, 2080 + + Mov BX, (DMABUFFERLENGTH*2)/16 + (FOURIERBUFFERLENGTH*2)/16 + Add BX, DX + + ; Allocate MixSegment first + Mov AH, 48h + + Int 21h + JNC InitSound1 + +InitSoundNoMemory: + Mov SI, Offset SB16NoMemoryMsg + Ret + +InitSound1: + Mov MixSegment, AX + Add AX, DX + Mov DMASegment, AX + Add AX, (DMABUFFERLENGTH*2)/16 + Mov FourierSegment, AX + Sub DX, 2080 + Mov MixSegmentLength, DX + + Call SetIRQ + Call GetTempo + Call SetTempo + + Mov DX, 330h + Call DetectUART + JC DetectMIDI1 + + Mov MIDIPort, 330h + Jmp DetectMIDIEnd + +DetectMIDI1: + Mov DX, 300h + Call DetectUART + JC DetectMIDIEnd + + Mov MIDIPort, 300h + +DetectMIDIEnd: + Mov SI, Offset SB16Msg + + Mov AX, BasePort + Mov BX, IRQ + Mov CX, DMA + + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, BasePort + Call ResetDSP + + Call ResetUART + Call ResetIRQ + + ; Delay.. + Mov DX, BasePort + Add DL, 0Ch + + Mov CX, 1000 +ReInitSound1: + In AL, DX + Loop ReInitSound1 + + Call SetIRQ + Call ReinitUART + + Mov SI, Offset ReInitMsg + Mov BX, 40 + Call SetInfoLine + + Mov AL, Stereo + Call SetStereo + + Pop ES + Pop DS + PopA + + Ret + +EndP ReInitSound + Assume DS:Nothing + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Mov DX, CS:BasePort + Add DL, 0Ch + + Mov AL, 0D9h + Call SBOut + + Call ResetUART + + Mov AX, BasePort + Call ResetDSP + + Call ResetDSPDMA + Call ResetDSPIRQ + + Mov AX, IMR + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Mov AX, MixSegment + Test AX, AX + JZ UnInitSound1 + + Mov ES, AX + Mov AH, 49h ; Release MixSegment + Int 21h + + Call ResetIRQ + +UnInitSound1: + Ret + +EndP UnInitSound + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + Push CS + Pop DS + Assume DS:Driver + +Poll1: + Call [UARTBufferEmpty] + JNC PollEnd + + Xor BX, BX + + ClI + + Mov BL, MIDIBufferHead + Cmp BL, MIDIBufferTail + JZ PollEnd ; Nothing in queue + + Inc BL + Mov AL, [MIDIBuffer+BX] + Mov MIDIBufferHead, BL + + Call [UARTSend] + Jmp Poll1 + +PollEnd: + StI + + Ret + +EndP Poll + Assume DS:Nothing + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Push AX + Push BX + Push DX + + Push BX + + Mov AX, MixSpeed + Mov BX, AX + Xor DX, DX + + ShL AX, 1 + RCL DX, 1 ; DX:AX = Mixspeed*2 + + ShR BX, 1 ; BX = Mixspeed/2 + + Add AX, BX + AdC DX, 0 ; DX:AX = Mixspeed*2.5 + + Pop BX ; BX = tempo + Div BX + + Mov BytesToMix, AX + + Pop DX + Pop BX + Pop AX + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + +; Mov CS:MixVolumeSet, AX + +; SetMixVolumeChain: + PushA + Push DS + +; Cmp CS:Surround, 0 +; JE SetMixVolumeSurround +; +; Mov BX, 49152 +; Mul BX +; Mov AX, DX +; +; SetMixVolumeSurround: + Mov BX, AX ; BX = MixVolume + Mov CS:MixVolume, AX + + Mov AX, CS:MixSegment + Test AX, AX + JZ SetMixVolume2 + + Mov DS, AX + + Mov CX, MIXTABLESIZE/2 + Mov SI, MIXTABLESIZE-2; Starting point - working backwards + +SetMixVolume1: + Mov AX, CX + + Dec AX ; AH = volume, AL = wave value. + Xor DX, DX + XChg AH, DL ; DL = Volume, AX = wave value + CBW + + IMul DX ; DX:AX = Volume * Wave Value + ; Ranges -8192->8128 + + IMul BX ; DX:AX = Volume * Wave Value * Mixing Volume + ; Ranges -1048576->1040384 + + Add AX, 64 + AdC DX, 0 + + ShRD AX, DX, 7 + Mov [SI], AX + Sub SI, 2 + + Dec CX + JNZ SetMixVolume1 + +SetMixVolume2: + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS: RecalculateAllVolumes + + Pop DS + PopA + + Ret + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Cmp CS:MixSegment, 0 + JE SetStereo1 + + Mov CS:Stereo, AL + Mov AX, CS:BasePort + Call ResetDSP + + Mov ES, CS:MixSegment + Mov CX, CS:MixSegmentLength + Mov DI, MIXTABLESIZE + ShL CX, 2 + Xor EAX, EAX + Rep StosD + + Call StartSB16 + +SetStereo1: + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include loadsam.inc + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset SB16ScreenList + + ClC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far ; Returns AX, given DI + + Xor AH, AH + Mov AL, [CS:VolumeTable+DI] + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far ; Given AX, DI + + Push DS + Push DX + + Push CS + Pop DS + Assume DS:Driver + + Mov [VolumeTable+DI], AL + + Mov DX, BasePort + Add DL, 4 + Mov AL, 30h + Mov AH, [VolumeTable] + ShL AH, 3 + Out DX, AX + + Mov AL, 31h + Mov AH, [VolumeTable+1] + ShL AH, 3 + Out DX, AX + + Mov AL, 44h + Mov AH, [VolumeTable+2] + ShL AH, 4 + Out DX, AX + + Mov AL, 45h + Mov AH, [VolumeTable+3] + ShL AH, 4 + Out DX, AX + + Mov AL, 46h + Mov AH, [VolumeTable+4] + ShL AH, 4 + Out DX, AX + + Mov AL, 47h + Mov AH, [VolumeTable+5] + ShL AH, 4 + Out DX, AX + + Pop DX + Pop DS + Ret + +EndP SetVariable + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetWaveForm Far ; Given ES:DI = destination + Assume DS:Nothing ; want 2048 samples. + + PushA + Push DS + + Mov DS, FourierSegment + Mov SI, FourierBufferStart + Mov CX, 2048 + +GetWaveForm1: + MovsW + And SI, (FOURIERBUFFERLENGTH*2)-1 + Loop GetWaveForm1 + + Pop DS + PopA + + Ret + +EndP GetWaveForm + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. + +StopAfterPlay DW 0 +DefaultChannels DW 64 +DriverFlags DW 4 + DW 4 Dup (0) + + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + DW 0 + DW Offset GetWaveform + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/SB16K6.ASM b/SoundDrivers/SB16K6.ASM new file mode 100755 index 0000000..c661467 --- /dev/null +++ b/SoundDrivers/SB16K6.ASM @@ -0,0 +1,2287 @@ + + + .586P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;********************************** + +TRACEENABLED = 0 +CREATENEWLOGFILE = 1 + +include debug.inc + +STEREOENABLED EQU 1 +DMABUFFERLENGTH EQU 8192 +MIXRESOLUTION EQU 32 ; 32 bit mixing for the SB16 +OUTPUTFILTERENABLED EQU 1 +FOURIERBUFFERLENGTH EQU 2048 ; 2048 samples + +FPSave DB 128 Dup (0) + +SB16Msg DB "Sound Blaster 16 3DNOW!", 13 + DB "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, DMA ", 0FDh, "D", 0 + +SB16NoMemoryMsg DB "Sound Blaster 16 3DNOW!", 13 + DB "Error: Insufficient memory", 0 + +ReinitMsg DB "Sound Blaster 16 reinitialised", 0 + +DriverName DB "ITSB16.3DN", 0 + +DSPVersion DW 0 +DSPIRQValue DB 0 +DSPDMAValue DB 0 +Forced DB 0 +Stereo DB 0 +MixVolume DW 0 + +BytesToMix DW 1000 +SBMixConst DB 0 + +MixSegment DW 0 +FourierSegment DW 0 + +MixTransferOffset DW 0 +MixTransferRemaining DW 0 + +CONFIGURATIONOFFSET EQU $+128 +CONFIGSIZE EQU 20 +MixMode DW 0 +MixModeOffset DW 0 +DMASize DW 2048 +VolumeTable DB 6 Dup (0) + DB 0, 16, 96, 127 + DB 0, 0, 0, 0 + +IMR DW 0 +OldIRQHandler DD 0 + +MIDIPort DW 0 +MIDIBuffer DB 256 Dup (0) +MIDIBufferHead DB 0 +MIDIBufferTail DB 0 + +IRQData Label Word + DW 20h, 1111111111111110b ; IRQ 0 + DW 24h, 1111111111111101b ; IRQ 1 + DW 28h, 1111110111111011b ; IRQ 2 + DW 2Ch, 1111111111110111b ; IRQ 3 + DW 30h, 1111111111101111b ; IRQ 4 + DW 34h, 1111111111011111b ; IRQ 5 + DW 38h, 1111111110111111b ; IRQ 6 + DW 3Ch, 1111111101111111b ; IRQ 7 + DW 1C0h, 1111111011111011b ; IRQ 8 + DW 1C4h, 1111110111111011b ; IRQ 9 + DW 1C8h, 1111101111111011b ; IRQ 10 + DW 1CCh, 1111011111111011b ; IRQ 11 + DW 1D0h, 1110111111111011b ; IRQ 12 + DW 1D4h, 1101111111111011b ; IRQ 13 + DW 1D8h, 1011111111111011b ; IRQ 14 + DW 1DCh, 0111111111111011b ; IRQ 15 + + +;********************************** + +SB16ScreenList Label + DW 8 + DW Near Ptr IdleFunctionList + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr SB16HeaderLine + + DW Near Ptr VolumeText + DW Near Ptr VolumeBox1 + DW Near Ptr VolumeBox2 + + DW Near Ptr DriverText + + DW Near Ptr MasterVolumeLeft ; 8 + DW Near Ptr MasterVolumeRight ; 9 + DW Near Ptr TrebleVolumeLeft ; 10 + DW Near Ptr TrebleVolumeRight ; 11 + DW Near Ptr BassVolumeLeft ; 12 + DW Near Ptr BassVolumeRight ; 13 + + DW Near Ptr MixModeText + DW Near Ptr MixModeButton1 ; 15 + DW Near Ptr MixModeButton2 ; 16 + + DW Near Ptr FrequencyText ; 17 + + DW Near Ptr FilterText ; 18 + DW Near Ptr FilterBox1 + DW Near Ptr FilterBox2 + + DW Near Ptr FilterFrequency1 ; 21 + DW Near Ptr FilterFrequency2 + DW Near Ptr FilterFrequency3 + DW Near Ptr FilterFrequency4 + + DW Near Ptr FilterVolume1 ; 25 + DW Near Ptr FilterVolume2 + DW Near Ptr FilterVolume3 + DW Near Ptr FilterVolume4 + + DW 0 + +SB16HeaderLine DW 10 + DB "Sound Blaster 16 3DNow! Driver", 0 + +DriverText DW 1 + DB 31, 48 + DB 21h + DB "Sound Blaster 16 Driver 1.4 for Impulse Tracker", 0 + +VolumeText DW 1 + DB 2, 13 + DB 20h + DB "Master Volume Left", 13 + DB "Master Volume Right", 13 + DB 13 + DB 13 + DB "Treble Left", 13 + DB "Treble Right", 13 + DB "Bass Left", 13 + DB "Bass Right", 13 + DB 0 + +VolumeBox1 DW 0 + DB 21, 12, 27, 15 + DB 25 + +VolumeBox2 DW 0 + DB 14, 16, 18, 21 + DB 25 + +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +IdleFunctionList DD 0 + DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +MasterVolumeLeft DW 9 + DB 22, 13 + DW 0, 31 + DW 9, 0 + DW 0FFFFh, 9, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +MasterVolumeRight DW 9 + DB 22, 14 + DW 0, 31 + DW 9, 1 + DW 8, 10, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +TrebleVolumeLeft DW 9 + DB 15, 17 + DW 0, 15 + DW 9, 2 + DW 9, 11, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +TrebleVolumeRight DW 9 + DB 15, 18 + DW 0, 15 + DW 9, 3 + DW 10, 12, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +BassVolumeLeft DW 9 + DB 15, 19 + DW 0, 15 + DW 9, 4 + DW 11, 13, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +BassVolumeRight DW 9 + DB 15, 20 + DW 0, 15 + DW 9, 5 + DW 12, 15, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +MixModeText DW 1 + DB 2, 23 + DB 20h + DB "Mixing Mode", 0 + +FrequencyText DW 1 + DB 2, 48 + DB 20h + DB "Playback Frequency: ", 0FDh, "DHz", 0 +MixSpeed DW 45454 + DW 0 + +MixModeButton1 DW 2 + DW 13, 16, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment1 DW 0 + DW 0 + DW Offset SetMixMode +DriverSegment2 DW 0 + DB 3, 25, 32, 27, 8 + DB 0 + DB " 3DNow!, Non-Interpolated", 0 + +MixModeButton2 DW 2 + DW 15, 18, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment3 DW 0 + DW 1 + DW Offset SetMixMode +DriverSegment4 DW 0 + DB 3, 28, 32, 30, 8 + DB 0 + DB " 3DNow!, Filtered", 0 + +FilterText DW 1 + DB 2, 39 + DB 20h + DB "Output Equalizer", 13 + DB 13 + DB " Low Frequency Band", 13 + DB " Med Low Frequency Band", 13 + DB "Med High Frequency Band", 13 + DB " High Frequency Band", 0 + +FilterBox1 DW 0 + DB 25, 40, 47, 45 + DB 25 + +FilterBox2 DW 0 + DB 52, 40, 74, 45 + DB 25 + +FilterFrequency1 DW 14 + DB 26, 41 + DW 0, 127 + DW 9, 6 + DW 16, 22, 25, 25 + DW 0FFFFh, 0FFFFh + DW 20 + +FilterFrequency2 DW 14 + DB 26, 42 + DW 0, 127 + DW 9, 7 + DW 21, 23, 26, 26 + DW 0FFFFh, 0FFFFh + DW 20 + +FilterFrequency3 DW 14 + DB 26, 43 + DW 0, 127 + DW 9, 8 + DW 22, 24, 27, 27 + DW 0FFFFh, 0FFFFh + DW 20 + +FilterFrequency4 DW 14 + DB 26, 44 + DW 0, 127 + DW 9, 9 + DW 23, 0FFFFh, 28, 28 + DW 0FFFFh, 0FFFFh + DW 20 + +FilterVolume1 DW 14 + DB 53, 41 + DW 0, 255 + DW 9, 10 + DW 16, 26, 21, 21 + DW 0FFFFh, 0FFFFh + DW 20 + +FilterVolume2 DW 14 + DB 53, 42 + DW 0, 255 + DW 9, 11 + DW 25, 27, 22, 22 + DW 0FFFFh, 0FFFFh + DW 20 + +FilterVolume3 DW 14 + DB 53, 43 + DW 0, 255 + DW 9, 12 + DW 26, 28, 23, 23 + DW 0FFFFh, 0FFFFh + DW 20 + +FilterVolume4 DW 14 + DB 53, 44 + DW 0, 255 + DW 9, 13 + DW 27, 0FFFFh, 24, 24 + DW 0FFFFh, 0FFFFh + DW 20 + + +; ÄÄ MixingRoutines ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixBufferPos DW 0 + +include dma.inc +include mix.inc + +include m32bitm.mix +include m32bitmi.mix + +ALIGN 2 + +MixFunctionTables Label + +include m32bitm.inc +include m32bitmi.inc +include mnomix.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +RelocationTable Label Word + DW Offset DriverSegment1, Offset DriverSegment2 + DW Offset DriverSegment3, Offset DriverSegment4 + DW 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SBOut ; AL = data + ; DX = 2xCh + + Push AX + +SBOut1: + In AL, DX + Test AL, AL + JS SBOut1 + + Pop AX + Out DX, AL + + Ret + +EndP SBOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SBIn ; DX = 2xEh, returns AL + +SBIn1: + In AL, DX + Test AL, AL + JNS SBIn1 + + Add DL, 0Ah-0Eh ; DX = 2xAh -> Data read port + In AL, DX + Add DL, 0Eh-0Ah + + Ret + +EndP SBIn + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectK63D + Assume DS:Driver + + PushFD + Pop EAX + Mov EBX, EAX + Xor EAX, 00200000h + Push EAX + PopFD + PushFD + Pop EAX + Cmp EAX, EBX + JZ DetectK63DFail + + Mov EAX, 80000000h + DB 0Fh, 0A2h ; CPUID + Cmp EAX, 80000000h + JBE DetectK63DFail + + Mov EAX, 80000001h + DB 0Fh, 0A2h + And EDX, 80800000h + Cmp EDX, 80800000h + JNE DetectK63DFail + + DB 85h + +DetectK63DFail: + StC + Ret + +EndP DetectK63D + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectUART ; Given DX = Port + +; From SB-DevKit + + ClI + + Inc DX + Xor CX, CX + +DetectUART1: + In AL, DX + Test AL, 40h ; Ready for output + LoopNZ DetectUART1 + JNZ DetectUARTError + + Mov AL, 0FFh ; Reset! + Out DX, AL + + Xor CX, CX + +DetectUART2: + In AL, DX + Test AL, 80h + JNZ DetectUART3 + + Dec DX + In AL, DX + Inc DX + Cmp AL, 0FEh + JE DetectUART4 + +DetectUART3: + Loop DetectUART2 + +DetectUARTError: + StI + StC + Ret + +DetectUART4: ; Now to shove it into 'intelligent' mode. + Xor CX, CX + +DetectUART5: + In AL, DX + Test AL, 40h + LoopNZ DetectUART5 + JNZ DetectUARTError + + Mov AL, 3Fh ; Intelligent mode! + Out DX, AL + +DetectUART6: + Xor CX, CX + +DetectUART7: + In AL, DX + Test AL, 80h + JNZ DetectUART8 + + Dec DX + In AL, DX + Inc DX + Cmp AL, 0FEh + JE DetectUART9 + +DetectUART8: + Loop DetectUART7 + + Jmp DetectUARTError + +DetectUART9: + StI + ClC + Ret + +EndP DetectUART + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReinitUART + + Mov DX, MIDIPort + Test DX, DX + JZ ReinitUART1 + + Call DetectUART + +ReinitUART1: + Ret + +EndP ReinitUART + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetUART + + Mov DX, MIDIPort + Test DX, DX + JZ ResetUART1 + + Inc DX + + Mov AL, 0FFh + Out DX, AL + +ResetUART1: + Ret + +EndP ResetUART + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixMode Far + + Push CS + Pop ES + Mov DI, Offset MixMode + + Ret + +EndP GetMixMode + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixMode Far + + Mov AX, [SI+22] + + ClI + + Mov CS:MixMode, AX + + Mov BX, 60 + Mul BX + Mov CS:MixModeOffset, AX + + StI + + Mov AX, 1 + Ret + +EndP SetMixMode + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SBGetRegister + + Out DX, AL + Inc DX + In AL, DX + Dec DX + + Ret + +EndP SBGetRegister + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetSBMixConst ; Work out value.. and nearest + ; mixspeed value. + + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, CmdLineMixSpeed + Mov CX, MixSpeed + Test AX, AX + JZ GetSBMixConst1 + + Mov CX, 45454 + Cmp AX, CX + JA GetSBMixConst1 + + Mov CX, 12000 + Cmp AX, CX + JB GetSBMixConst1 + + Mov CX, AX + +GetSBMixConst1: + Mov AX, 1000 + Mul AX + Div CX + Mov AH, AL + Neg AH + Mov SBMixConst, AH + + MovZX BX, AL + Mov AX, 1000 + Mul AX + Div BX + Mov MixSpeed, AX + + FNInit + FILd DWord Ptr [MixSpeed] + FMul FreqMultiplier + FStP FreqMultiplier + + Mov BX, 12000 + Xor DX, DX + Div BX + Mov FourierBufferStepOffset, AX + Mov FourierBufferStepFractional, DX + + Pop DS + PopA + Ret + +EndP GetSBMixConst + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetDSP Far ; AX = Port + + Push AX + Push CX + Push DX + + Mov DX, AX + Add DL, 6 + Mov AL, 1 + Out DX, AL + + In AL, DX + In AL, DX + In AL, DX + In AL, DX + + Xor AL, AL + Out DX, AL + + Add DL, 8 + Mov CX, 200 + +ResetDSP1: + In AL, DX + Test AL, AL + JS ResetDSP2 + Loop ResetDSP1 + Jmp ResetDSP3 + +ResetDSP2: + Sub DL, 4 + In AL, DX + Cmp AL, 0AAh + JE ResetDSP4 + Add DL, 4 + Loop ResetDSP1 + +ResetDSP3: + StC + +ResetDSP4: + Pop DX + Pop CX + Pop AX + Ret + +EndP ResetDSP + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetDSPIRQ + + Mov DX, CS:BasePort + Add DL, 4 + Mov AH, CS:DSPIRQValue + Mov AL, 80h + Out DX, AX + + Ret + +EndP ResetDSPIRQ + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetDSPDMA + + Mov DX, CS:BasePort + Add DL, 4 + Mov AH, CS:DSPDMAValue + Mov AL, 81h + Out DX, AX + + Ret + +EndP ResetDSPDMA + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far + + Push CS + Pop DS + Assume DS:Driver + + Mov Forced, AL + + Call DetectK63D + JC DetectCardFailure + + Mov AX, BasePort + Cmp AX, 0FFFFh + JE DetectCard1 + + Cmp AX, 210h + JB DetectCard9 + Cmp AX, 280h + JA DetectCard9 + + Call ResetDSP + JNC DetectCard2 + + Ret + +DetectCard1: + Mov AX, 210h + +DetectCard2: + Call ResetDSP + JNC DetectCard3 + Add AL, 10h + Cmp AL, 80h + JBE DetectCard2 + +DetectCard9: + StC + Ret + +DetectCard3: ; OK... DSP found. + ; Get DSP version + Mov BasePort, AX + + Mov DX, AX + Add DL, 0Ch ; 2xCh -> Data ready to send... + +DetectCardOuputLoop1: + In AL, DX + Test AL, AL + JS DetectCardOuputLoop1 + + Mov AL, 0E1h ; Get DSP version command + Out DX, AL + + Add DL, 0Eh-0Ch ; DX = 2xEh -> Data available status + + Call SBIn + Mov AH, AL ; AH = Major version number + Call SBIn ; AL = Minor version number + + Cmp AH, 4 ; SB DSP = 4.00+ + JAE DetectCard5 + +DetectCard4: + StC + Ret + +DetectCard5: + Mov DSPVersion, AX + + Add DL, 04h-0Eh ; 2x4h = Mixer index port + Mov AL, 80h ; IRQ select + Out DX, AL + Inc DL ; 2x5h = Mixer data port + + In AL, DX + + Dec DL + + Mov DSPIRQValue, AL + ; OK.. now get IRQ, or set IRQ + Mov BX, IRQ + Cmp BX, 0FFFFh + JE DetectCardIRQ1 + Cmp Forced, 0 + JE DetectCardIRQ1 + + Mov AH, 11h + Cmp BL, 2 + JE SetCardIRQ1 + Cmp BL, 9 + JE SetCardIRQ1 + + Mov AH, 12h + Cmp BL, 5 + JE SetCardIRQ1 + + Mov AH, 14h + Cmp BL, 7 + JE SetCardIRQ1 + + Mov AH, 18h + Cmp BL, 10 + JE SetCardIRQ1 + + StC + Ret + +SetCardIRQ1: + Mov AL, 80h + Out DX, AL + Inc DL + Mov AL, AH + Out DX, AL + Dec DL + Jmp DetectCard6 + +DetectCardIRQ1: + Mov BX, 2 + Test AL, 1 + JNZ DetectCardIRQ2 + + Mov BL, 5 + Test AL, 2 + JNZ DetectCardIRQ2 + + Mov BL, 7 + Test AL, 4 + JNZ DetectCardIRQ2 + + Mov BL, 10 + Test AL, 8 + JNZ DetectCardIRQ2 + + StC + Ret + +DetectCardIRQ2: + Cmp IRQ, 0FFFFh + JE DetectCardIRQ3 + + Cmp BX, IRQ + JE DetectCard6 + +DetectCardFailure: + StC + Ret + +DetectCardIRQ3: + Mov IRQ, BX + +DetectCard6: ; Detect DMA + Mov AL, 81h ; DMA select + Out DX, AL + Inc DL + In AL, DX ; AL = DMA + Dec DL + + Mov DSPDMAValue, AL + + Mov BX, DMA + Cmp BX, 0FFFFh + JE DetectCardDMA1 + Cmp Forced, 0 + JE DetectCardDMA1 + + Mov CL, 1 + Cmp BX, 1 + JB SetCardDMA1 + + Mov CL, 2 + JE SetCardDMA1 + + Cmp BX, 3 + JB DetectCard7 + + Mov CL, 8 + JE DetectCard7 + + Mov CL, 20h + Cmp BX, 5 + JB DetectCard7 + JE SetCardDMA1 + + Mov CL, 80h + Cmp BX, 7 + JA DetectCard7 + JE SetCardDMA1 + + Mov CL, 40h + +SetCardDMA1: + And AL, 0Bh + Test CL, 0Bh + JZ SetCardDMA4 + + Xor AL, AL + +SetCardDMA4: + Or CL, AL + + Mov AL, 81h + Out DX, AL + Inc DL + Mov AL, CL + Out DX, AL + Jmp DetectCard7 + +DetectCardDMA1: + Mov BX, 5 + Test AL, 20h + JNZ DetectCardDMA2 + + Inc BL + Test AL, 40h + JNZ DetectCardDMA2 + + Inc BL + Test AL, 80h + JNZ DetectCardDMA2 + + Mov BL, 0 + Test AL, 1 + JNZ DetectCardDMA2 + + Inc BL + Test AL, 2 + JNZ DetectCardDMA2 + + Add BL, 2 + Test AL, 8 + JNZ DetectCardDMA2 + +DetectCard8: + Call ResetDSPIRQ + StC + Ret + +DetectCardDMA2: + Cmp DMA, 0FFFFh + JE DetectCardDMA3 + + Cmp BX, DMA + JNE DetectCard8 + +DetectCardDMA3: + Mov DMA, BX + +DetectCard7: + Mov EAX, 'Jeff' + + ClC + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include mmxmsam.inc +include fourier.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc AckIRQ + Assume DS:Driver + + Mov AL, 20h + Cmp CS:IRQ, 7 + JBE AckIRQ1 + + Out 0A0h, AL + +AckIRQ1: + Out 20h, AL + Ret + +EndP AckIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc CheckMIDI + + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Xor BX, BX + Mov DX, MIDIPort + + Mov BL, [MIDIBufferTail] + Test DX, DX + JZ CheckMIDIEnd + + Inc DX + Mov CX, 0FFFFh + +CheckMIDIAgain: + In AL, DX + + Test AL, 80h + LoopNZ CheckMIDIAgain + + Dec DX + In AL, DX + + Cmp AL, 0F0h + JAE CheckMIDIEnd + + Inc BL + Cmp BL, MIDIBufferHead + JE CheckMIDIEnd + + Mov [MIDIBuffer+BX], AL + Mov [MIDIBufferTail], BL +; Jmp CheckMIDIAgain + +CheckMIDIEnd: + Pop DS + Ret + +EndP CheckMIDI + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SB16IRQHandler + + PushAD + Push DS + Push ES + + CLD + +SBIRQAgain: + Mov AX, CS + Mov DS, AX + Assume DS:Driver + + Mov DX, BasePort + Add DL, 4 ; Mixer Port + Mov AL, 82h + Out DX, AL + Inc DL ; DX = BasePort+5 + In AL, DX + +Comment ~ + Test AL, 1 + JZ SB8BitDigitalInterruptEnd + +SB8BitDigitalInterrupt: + Push AX + Add DL, 0Eh-5 + In AL, DX + Pop AX + +SB8BitDigitalInterruptEnd: + + ~ + Test AL, 4 + JZ SBMIDIInterruptEnd + + Push AX + Call CheckMIDI + Pop AX + +SBMIDIInterruptEnd: + Test AL, 2 + JNZ SBDigitalInterrupt + + Call AckIRQ + Jmp SBIRQEnd + +SBDigitalInterrupt: + FNSave [FPSave] + + Mov DX, BasePort + Add DL, 0Fh + In AL, DX ; 16-bit IRQ ack. + + Call AckIRQ + + Mov AX, MixBufferPos + Mov BX, AX + Mul DMASize + Cmp AX, DMABUFFERLENGTH + JB SB16IRQHandler2 + + Xor AX, AX + Xor BX, BX + +SB16IRQHandler2: + Inc BX + Mov MixBufferPos, BX + + + ; OK... time to get next block + ; Check whether stereo thing is on.. + ; + LES DI, [ActualDMAPtr] + Mov BX, DMASize ; BX = bytes required + Add DI, AX + ShR BX, 1 + ; BX = samples required + Call SaveEMSPageFrame + + Cmp MixTransferRemaining, 0 + JNE SB16IRQHandler4 + Assume DS:Nothing + +SB16IRQHandler3: + Push BX + Push CX + Push BP + Push ES + Push DI + + Call Update + Call MixSamples + Call UpdateFourierBuffer + + Pop DI + Pop ES + Pop BP + Pop CX + Pop BX + +SB16IRQHandler4: + Mov DS, MixSegment + Mov SI, MixTransferOffset + Mov DX, BX ; DX = samples to transfer + Cmp DX, MixTransferRemaining + JBE SB16IRQHandler5 + + Mov DX, MixTransferRemaining + +SB16IRQHandler5: + +include mmxtrans.inc + + Sub MixTransferRemaining, DX ; } Memory write + Sub BX, DX + JNZ SB16IRQHandler3 + + Mov MixTransferOffset, SI ; } Memory write + + Call RestoreEMSPageFrame + + FNRstor [CS:FPSave] + +SBIRQEnd: + Pop ES + Pop DS + PopAD + IRet + +EndP SB16IRQHandler + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + + PushAD + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Add DI, Offset IRQData + Mov BX, [DI] + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset SB16IRQHandler + + XChg [ES:BX], EAX + Mov OldIRQHandler, EAX + + Mov AX, IMR + And AX, [DI+2] + + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Pop ES + Pop DS + PopAD + + Ret + +EndP SetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIRQ + + PushAD + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Mov BX, [IRQData+DI] + + Mov EAX, OldIRQHandler + Mov [ES:BX], EAX + + Pop ES + Pop DS + PopAD + + Ret + +EndP ResetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StartSB16 ; + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + ; Setup DMA + Mov BX, MixSegment + Mov AX, 80 + Mov DX, DMA + Mov DI, DMABUFFERLENGTH + Call SetDMA + + LES DI, ActualDMAPtr + Xor AX, AX + Mov CX, DMABUFFERLENGTH/2 + Rep StosW + + Mov MixBufferPos, 0 + Mov MixTransferRemaining, 0 + + Mov DX, BasePort + Add DL, 0Ch + + Mov AL, 0D1h ; turn on speaker + Call SBOut + + Mov AL, 40h ; time constant + Call SBOut + Mov AL, SBMixConst + Call SBOut + + Mov AL, 0B6h ; 16 bit, DAC + Call SBOut + Mov AL, Stereo + ShL AL, 5 + Or AL, 10h + Call SBOut + + Mov AX, DMASize + ShR AX, 1 + Dec AX + + Call SBOut ; DMALength, Lo + Mov AL, AH + Call SBOut + + Pop ES + Pop DS + PopA + + Ret + + Assume DS:Nothing + +EndP StartSB16 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixerRegisters + + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Pop DS + + Ret + +EndP GetMixerRegisters + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + Mov SI, Offset RelocationTable + +RelocationFix: + LodsW + Test AX, AX + JZ RelocationEnd + Mov BX, AX + Mov [BX], DS + Jmp RelocationFix + +RelocationEnd: + Call GetEMSPageFrame + Mov EMSPageFrame, AX + + In AL, 0A1h + Mov AH, AL + In AL, 21h + Mov IMR, AX + + Mov DX, BasePort + Add DL, 4 + + Mov AL, 30h + Call SBGetRegister + ShR AL, 3 + Mov VolumeTable, AL + + Mov AL, 31h + Call SBGetRegister + ShR AL, 3 + Mov [VolumeTable+1], AL + + Mov AL, 44h + Call SBGetRegister + ShR AL, 4 + Mov [VolumeTable+2], AL + + Mov AL, 45h + Call SBGetRegister + ShR AL, 4 + Mov [VolumeTable+3], AL + + Mov AL, 46h + Call SBGetRegister + ShR AL, 4 + Mov [VolumeTable+4], AL + + Mov AL, 47h + Call SBGetRegister + ShR AL, 4 + Mov [VolumeTable+5], AL + + Call GetSBMixConst + + ; Parags to allocate = (8/(.4*31*16))*MixSpeed + 2080 + ; = .04032258*MixSpeed = (65536*.04032258*MixSpeed) / 65536 + + Mov AX, 2643 + Mul MixSpeed + Add AX, 0FFFFh + AdC DX, 5+(DMABUFFERLENGTH*2)/16+(FOURIERBUFFERLENGTH*2)/16 + Mov BX, DX + + ; Allocate MixSegment first + Mov AH, 48h + + Int 21h + JNC InitSound1 + +InitSoundNoMemory: + Mov SI, Offset SB16NoMemoryMsg + Ret + +InitSound1: + Mov MixSegment, AX + Add AX, DX + Sub AX, (FOURIERBUFFERLENGTH*2)/16 + Mov FourierSegment, AX + + Call SetIRQ + Call GetTempo + Call SetTempo + + Mov DX, 330h + Call DetectUART + JC DetectMIDI1 + + Mov MIDIPort, 330h + Jmp DetectMIDIEnd + +DetectMIDI1: + Mov DX, 300h + Call DetectUART + JC DetectMIDIEnd + + Mov MIDIPort, 300h + +DetectMIDIEnd: + Call CalculateFilterCoefficients + + Mov SI, Offset SB16Msg + + Mov AX, BasePort + Mov BX, IRQ + Mov CX, DMA + + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, BasePort + Call ResetDSP + + Call ResetUART + Call ResetIRQ + + ; Delay.. + Mov DX, BasePort + Add DL, 0Ch + + Mov CX, 1000 +ReInitSound1: + In AL, DX + Loop ReInitSound1 + + Call SetIRQ + Call ReinitUART + + Mov SI, Offset ReInitMsg + Mov BX, 40 + Call SetInfoLine + + Mov AL, Stereo + Call SetStereo + + Pop ES + Pop DS + PopA + + Ret + +EndP ReInitSound + Assume DS:Nothing + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Call GotoHomeDirectory + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, 3D02h ; Read write access + Mov DX, Offset DriverName + Int 21h + JC SaveConfig2 + + Mov BX, AX + + Mov AX, 4200h + Xor CX, CX + Mov DX, Offset CONFIGURATIONOFFSET + Int 21h + JC SaveConfig1 + + Mov AH, 40h + Mov CX, CONFIGSIZE + Mov DX, Offset MixMode + Int 21h + +SaveConfig1: + Mov AH, 3Eh + Int 21h + +SaveConfig2: + Mov DX, CS:BasePort + Add DL, 0Ch + + Mov AL, 0D9h + Call SBOut + + Call ResetUART + + Mov AX, BasePort + Call ResetDSP + + Call ResetDSPDMA + Call ResetDSPIRQ + + Mov AX, IMR + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Mov AX, MixSegment + Test AX, AX + JZ UnInitSound1 + + Mov ES, AX + Mov AH, 49h ; Release MixSegment + Int 21h + + Call ResetIRQ + +UnInitSound1: + Ret + +EndP UnInitSound + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + Push CS + Pop DS + Assume DS:Driver + +Poll1: + Call [UARTBufferEmpty] + JNC PollEnd + + Xor BX, BX + + ClI + + Mov BL, MIDIBufferHead + Cmp BL, MIDIBufferTail + JZ PollEnd ; Nothing in queue + + Inc BL + Mov AL, [MIDIBuffer+BX] + Mov MIDIBufferHead, BL + + Call [UARTSend] + Jmp Poll1 + +PollEnd: + StI + + Ret + +EndP Poll + Assume DS:Nothing + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Push AX + Push BX + Push DX + + Push BX + + Mov AX, MixSpeed + Mov BX, AX + Xor DX, DX + + ShL AX, 1 + RCL DX, 1 ; DX:AX = Mixspeed*2 + + ShR BX, 1 ; BX = Mixspeed/2 + + Add AX, BX + AdC DX, 0 ; DX:AX = Mixspeed*2.5 + + Pop BX ; BX = tempo + Div BX + + Mov BytesToMix, AX + + Pop DX + Pop BX + Pop AX + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + Mov CS:MixVolume, AX + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Jmp CS:RecalculateAllVolumes + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Cmp CS:MixSegment, 0 + JE SetStereo1 + + Mov CS:Stereo, AL + Mov AX, CS:BasePort + Call ResetDSP + + Call StartSB16 + +SetStereo1: + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc LoadSample Far ; Fix up end of sample bytes + + PushAD + Push DS + Push ES + Push FS + + Mov FS, CS:SongDataArea + Mov BP, AX + Add BP, BP + Mov BP, [FS:64910+BP] + + Xor CX, CX ; From the start of the sample.. + Call GetSampleLocation ; Returns DS:ESI, ECX = length + JC LoadSampleEnd ; Zero flag ON if 16 bit.. + + Xor EAX, EAX + Mov BL, [FS:BP+12h] + + Test BL, 10h ; Loop + JZ LoadSample2 + + Mov ESI, [FS:BP+34h] ; Start of loop + Test BL, 40h ; Pingpong? + JZ LoadSample1 + + Mov ESI, [FS:BP+38h] + Sub ESI, 2 + JNC LoadSample1 + + Xor ESI, ESI + +LoadSample1: + Test BL, 2 + JZ LoadSample4 + + Add ESI, ESI + +LoadSample4: + Int 3 + Mov AL, [SI] + Inc ESI + Int 3 + Mov AH, [SI] + +LoadSample2: + Mov ESI, [FS:BP+30h] + Test BL, 2 + JZ LoadSample3 + + Add ESI, ESI + +LoadSample3: + Int 3 + Mov [SI], AL + Inc ESI + Int 3 + Mov [SI], AH + +LoadSampleEnd: + Pop FS + Pop ES + Pop DS + PopAD + + StC + Ret + +EndP LoadSample + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset SB16ScreenList + + ClC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far ; Returns AX, given DI + + Xor AH, AH + Mov AL, [CS:VolumeTable+DI] + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +TempVariable DW 0 +Const1 DD 3F800000h + +Proc GetFilterFrequency ; Given AL= Freq + Assume DS:Driver + + ShL AX, 8 + Mov TempVariable, AX + FILD TempVariable + + FMul FreqParameterMultiplier ; -i/(24*256) + FLd ST + FRndInt + FSub ST(1), ST + FXCh + F2XM1 + FLd1 + FAdd + FScale ; = 2^(i/24*256) + FMul FreqMultiplier ; = r + + FLd1 ; 1, c + FAdd ST, ST(1) ; 1+c, c + FDivR Const1 ; 1/(1+c), c + FSt DWord Ptr [SI] + FMul + FStP DWord Ptr [SI+4] + FStP ST + + Ret + +EndP GetFilterFrequency + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Const1On16 DD 3D000000h ; actually 1 on 32 + +Proc CalculateFilterCoefficients + Assume DS:Driver + + PushA + + FNInit + FLdCW NewControlWord + + Mov AL, [VolumeTable+6] + Mov SI, Offset FilterCoefficients + ShR AL, 1 + Call GetFilterFrequency + + Mov AL, [VolumeTable+7] ; FilterFrequency1 + Add SI, 8 + Call GetFilterFrequency + + Mov AL, [VolumeTable+8] ; FilterFrequency1 + Add SI, 8 + Call GetFilterFrequency + + Mov AL, [VolumeTable+9] ; FilterFrequency1 + Add SI, 8 + Call GetFilterFrequency + +; Now volumes + Mov SI, Offset VolumeTable+10 + Mov DI, Offset FilterVolumes + Xor AX, AX + Mov CX, 4 + +FilterVolumeLoop1: + LodSB + Mov TempVariable, AX + FILD TempVariable + FMul Const1On16 + FStP DWord Ptr [DI] + + Add DI, 4 + Loop FilterVolumeLoop1 + + PopA + Ret + +EndP CalculateFilterCoefficients + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far ; Given AX, DI + + Push DS + Push DX + + Push CS + Pop DS + Assume DS:Driver + + Mov [VolumeTable+DI], AL + + Cmp DI, 9 + JA SetVariable3 + + Cmp DI, 6 + JB SetVariable1 + + JE SetVariable2 + + Cmp AL, [VolumeTable+DI-1] + JAE SetVariable2 + + Mov AL, [VolumeTable+DI-1] + Mov [VolumeTable+DI], AL + +SetVariable2: + Cmp DI, 9 + JAE SetVariable3 + + Cmp AL, [VolumeTable+DI+1] + JBE SetVariable3 + + Mov AL, [VolumeTable+DI+1] + Mov [VolumeTable+DI], AL + +SetVariable3: + Call CalculateFilterCoefficients + Jmp SetVariableEnd + +SetVariable1: + Mov DX, BasePort + Add DL, 4 + Mov AL, 30h + Mov AH, [VolumeTable] + ShL AH, 3 + Out DX, AX + + Mov AL, 31h + Mov AH, [VolumeTable+1] + ShL AH, 3 + Out DX, AX + + Mov AL, 44h + Mov AH, [VolumeTable+2] + ShL AH, 4 + Out DX, AX + + Mov AL, 45h + Mov AH, [VolumeTable+3] + ShL AH, 4 + Out DX, AX + + Mov AL, 46h + Mov AH, [VolumeTable+4] + ShL AH, 4 + Out DX, AX + + Mov AL, 47h + Mov AH, [VolumeTable+5] + ShL AH, 4 + Out DX, AX + +SetVariableEnd: + Pop DX + Pop DS + Ret + +EndP SetVariable + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UARTOut + + Push CX + Push DX + Mov DX, CS:MIDIPort + Test DX, DX + JZ UARTOutEnd + + Push AX + Xor CX, CX + Inc DX + +UARTOut1: + In AL, DX + Test AL, 40h + LoopNZ UARTOut1 + + Pop AX + JNZ UARTOutEnd + + Dec DX + Out DX, AL + +UARTOutEnd: + Pop DX + Pop CX + + Ret + +EndP UARTOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +InterpretState DB 0 +InterpretType DB 0 + +Proc SendUARTOut Far ; Local interpreter activated with 0F0h 0F0h. + + Mov AH, CS:InterpretState + Cmp AH, 2 + JB SendUARTOut1 + +; In interpreter. + JE SendUARTOut3 + +; Have InterpretType, now get parameter, then return to normal. + + Cmp AL, 7Fh + JA SendUARTOut4 + + Push BX + + Mov BL, CS:InterpretType ; Want BX = InterpretType*64+Channel + ; + ShL BX, 6 + Add BL, [DI+20h] + And BX, 127 + Mov [CS:FilterParameters+BX], AL + + Pop BX + + Test SI, SI + JZ SendUARTOut4 + + Or Byte Ptr [SI], 64 + +SendUARTOut4: + Mov CS:InterpretState, 0 + Ret + +SendUARTOut3: + Cmp AL, 2 + JAE SendUARTOut4 + + Mov CS:InterpretType, AL + Jmp SendUARTOutStateInc + +SendUARTOut1: + Cmp AL, 0F0h + JNE SendUARTOut2 + +SendUARTOutStateInc: + Inc CS:InterpretState + Ret + +SendUARTOut2: + Test AH, AH + JZ SendUARTOutEnd + + Push AX + Mov AL, 0F0h + Call UARTOut + Pop AX + Mov CS:InterpretState, 0 + +SendUARTOutEnd: + Cmp AL, 0FCh + JE ResetFilters + Cmp AL, 0FAh + JE ResetFilters + + Cmp AL, 0FFh + JNE SendUARTOutNoClear + +ResetFilters: + PushA + Push ES + + Push CS + Pop ES + + Mov DI, Offset FilterParameters + Mov CX, 64 + Mov AL, 7Fh + Rep StosB + Mov CX, 64 + Xor AX, AX + Rep StosB + + Pop ES + PopA + +SendUARTOutNoClear: + Call UARTOut + Ret + +EndP SendUARTOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetWaveForm Far ; Given ES:DI = destination + Assume DS:Nothing ; want 2048 samples. + + PushA + Push DS + + Mov DS, FourierSegment + Mov SI, FourierBufferStart + Mov CX, 2048 + +GetWaveForm1: + MovsW + And SI, (FOURIERBUFFERLENGTH*2)-1 + Loop GetWaveForm1 + + Pop DS + PopA + + Ret + +EndP GetWaveForm + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. + +StopAfterPlay DW 0 +DefaultChannels DW 128 + DW 7 ; MIDI, hiqual + DW 4 Dup (0) + + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + + DW Offset SendUARTOut + + DW Offset GetWaveform + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/SB16MMX.ASM b/SoundDrivers/SB16MMX.ASM new file mode 100755 index 0000000..4c49440 --- /dev/null +++ b/SoundDrivers/SB16MMX.ASM @@ -0,0 +1,2272 @@ + + + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc +include mmx.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;********************************** + +TRACEENABLED = 0 +CREATENEWLOGFILE = 1 + +include debug.inc + +STEREOENABLED EQU 1 +DMABUFFERLENGTH EQU 8192 +MIXRESOLUTION EQU 32 ; 32 bit mixing for the SB16 +OUTPUTFILTERENABLED EQU 1 +FOURIERBUFFERLENGTH EQU 2048 ; 2048 samples + +FPSave DB 128 Dup (0) + +SB16Msg DB "Sound Blaster 16 MMX", 13 + DB "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, DMA ", 0FDh, "D", 0 + +SB16NoMemoryMsg DB "Sound Blaster 16 MMX", 13 + DB "Error: Insufficient memory", 0 + +ReinitMsg DB "Sound Blaster 16 reinitialised", 0 + +DefaultDriverName DB "ITSB16.MMX", 0 +DriverName DD 0 + +DSPVersion DW 0 +DSPIRQValue DB 0 +DSPDMAValue DB 0 +Forced DB 0 +Stereo DB 0 +MixVolume DW 0 + +BytesToMix DW 1000 +SBMixConst DB 0 + +MixSegment DW 0 +FourierSegment DW 0 + +MixTransferOffset DW 0 +MixTransferRemaining DW 0 + +CONFIGURATIONOFFSET EQU $+128 +CONFIGSIZE EQU 20 +MixMode DW 0 +MixModeOffset DW 0 +DMASize DW 2048 +VolumeTable DB 6 Dup (0) + DB 0, 16, 96, 127 + DB 0, 0, 0, 0 + +IMR DW 0 +OldIRQHandler DD 0 + +MIDIPort DW 0 +MIDIBuffer DB 256 Dup (0) +MIDIBufferHead DB 0 +MIDIBufferTail DB 0 + +IRQData Label Word + DW 20h, 1111111111111110b ; IRQ 0 + DW 24h, 1111111111111101b ; IRQ 1 + DW 28h, 1111110111111011b ; IRQ 2 + DW 2Ch, 1111111111110111b ; IRQ 3 + DW 30h, 1111111111101111b ; IRQ 4 + DW 34h, 1111111111011111b ; IRQ 5 + DW 38h, 1111111110111111b ; IRQ 6 + DW 3Ch, 1111111101111111b ; IRQ 7 + DW 1C0h, 1111111011111011b ; IRQ 8 + DW 1C4h, 1111110111111011b ; IRQ 9 + DW 1C8h, 1111101111111011b ; IRQ 10 + DW 1CCh, 1111011111111011b ; IRQ 11 + DW 1D0h, 1110111111111011b ; IRQ 12 + DW 1D4h, 1101111111111011b ; IRQ 13 + DW 1D8h, 1011111111111011b ; IRQ 14 + DW 1DCh, 0111111111111011b ; IRQ 15 + + +;********************************** + +SB16ScreenList Label + DW 8 + DW Near Ptr IdleFunctionList + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr SB16HeaderLine + + DW Near Ptr VolumeText + DW Near Ptr VolumeBox1 + DW Near Ptr VolumeBox2 + + DW Near Ptr DriverText + + DW Near Ptr MasterVolumeLeft ; 8 + DW Near Ptr MasterVolumeRight ; 9 + DW Near Ptr TrebleVolumeLeft ; 10 + DW Near Ptr TrebleVolumeRight ; 11 + DW Near Ptr BassVolumeLeft ; 12 + DW Near Ptr BassVolumeRight ; 13 + + DW Near Ptr MixModeText + DW Near Ptr MixModeButton1 ; 15 + DW Near Ptr MixModeButton2 ; 16 + DW Near Ptr MixModeButton3 ; 17 + DW Near Ptr MixModeButton4 ; 18 + + DW Near Ptr FrequencyText + + DW Near Ptr FilterText ; 20 + DW Near Ptr FilterBox1 + DW Near Ptr FilterBox2 + + DW Near Ptr FilterFrequency1 ; 23 + DW Near Ptr FilterFrequency2 + DW Near Ptr FilterFrequency3 + DW Near Ptr FilterFrequency4 + + DW Near Ptr FilterVolume1 ; 27 + DW Near Ptr FilterVolume2 + DW Near Ptr FilterVolume3 + DW Near Ptr FilterVolume4 + + DW 0 + + +SB16HeaderLine DW 10 + DB "Sound Blaster 16 Driver", 0 + +DriverText DW 1 + DB 31, 48 + DB 21h + DB "Sound Blaster 16 Driver 1.4 for Impulse Tracker", 0 + +VolumeText DW 1 + DB 2, 13 + DB 20h + DB "Master Volume Left", 13 + DB "Master Volume Right", 13 + DB 13 + DB 13 + DB "Treble Left", 13 + DB "Treble Right", 13 + DB "Bass Left", 13 + DB "Bass Right", 13 + DB 0 + +VolumeBox1 DW 0 + DB 21, 12, 27, 15 + DB 25 + +VolumeBox2 DW 0 + DB 14, 16, 18, 21 + DB 25 + +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +IdleFunctionList DD 0 + DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +MasterVolumeLeft DW 9 + DB 22, 13 + DW 0, 31 + DW 9, 0 + DW 0FFFFh, 9, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +MasterVolumeRight DW 9 + DB 22, 14 + DW 0, 31 + DW 9, 1 + DW 8, 10, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +TrebleVolumeLeft DW 9 + DB 15, 17 + DW 0, 15 + DW 9, 2 + DW 9, 11, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +TrebleVolumeRight DW 9 + DB 15, 18 + DW 0, 15 + DW 9, 3 + DW 10, 12, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +BassVolumeLeft DW 9 + DB 15, 19 + DW 0, 15 + DW 9, 4 + DW 11, 13, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +BassVolumeRight DW 9 + DB 15, 20 + DW 0, 15 + DW 9, 5 + DW 12, 15, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +MixModeText DW 1 + DB 2, 23 + DB 20h + DB "Mixing Mode", 0 + +FrequencyText DW 1 + DB 2, 48 + DB 20h + DB "Playback Frequency: ", 0FDh, "DHz", 0 +MixSpeed DW 45454 + DW 0 + +MixModeButton1 DW 2 + DW 13, 16, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment1 DW 0 + DW 0 + DW Offset SetMixMode +DriverSegment2 DW 0 + DB 3, 25, 32, 27, 8 + DB 0 + DB " MMX, Non-Interpolated", 0 + +MixModeButton2 DW 2 + DW 15, 17, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment3 DW 0 + DW 1 + DW Offset SetMixMode +DriverSegment4 DW 0 + DB 3, 28, 32, 30, 8 + DB 0 + DB " MMX, Interpolated", 0 + +MixModeButton3 DW 2 + DW 16, 18, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment5 DW 0 + DW 2 + DW Offset SetMixMode +DriverSegment6 DW 0 + DB 3, 31, 32, 33, 8 + DB 0 + DB " MMX, Volume Ramped", 0 + +MixModeButton4 DW 2 + DW 17, 23, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment7 DW 0 + DW 3 + DW Offset SetMixMode +DriverSegment8 DW 0 + DB 3, 34, 32, 36, 8 + DB 0 + DB " MMX, Filtered", 0 + +FilterText DW 1 + DB 2, 39 + DB 20h + DB "Output Equalizer", 13 + DB 13 + DB " Low Frequency Band", 13 + DB " Med Low Frequency Band", 13 + DB "Med High Frequency Band", 13 + DB " High Frequency Band", 0 + +FilterBox1 DW 0 + DB 25, 40, 47, 45 + DB 25 + +FilterBox2 DW 0 + DB 52, 40, 74, 45 + DB 25 + +FilterFrequency1 DW 14 + DB 26, 41 + DW 0, 127 + DW 9, 6 + DW 18, 24, 27, 27 + DW 0FFFFh, 0FFFFh + DW 20 + +FilterFrequency2 DW 14 + DB 26, 42 + DW 0, 127 + DW 9, 7 + DW 23, 25, 28, 28 + DW 0FFFFh, 0FFFFh + DW 20 + +FilterFrequency3 DW 14 + DB 26, 43 + DW 0, 127 + DW 9, 8 + DW 24, 26, 29, 29 + DW 0FFFFh, 0FFFFh + DW 20 + +FilterFrequency4 DW 14 + DB 26, 44 + DW 0, 127 + DW 9, 9 + DW 25, 0FFFFh, 30, 30 + DW 0FFFFh, 0FFFFh + DW 20 + +FilterVolume1 DW 14 + DB 53, 41 + DW 0, 255 + DW 9, 10 + DW 18, 28, 23, 23 + DW 0FFFFh, 0FFFFh + DW 20 + +FilterVolume2 DW 14 + DB 53, 42 + DW 0, 255 + DW 9, 11 + DW 27, 29, 24, 24 + DW 0FFFFh, 0FFFFh + DW 20 + +FilterVolume3 DW 14 + DB 53, 43 + DW 0, 255 + DW 9, 12 + DW 28, 30, 25, 25 + DW 0FFFFh, 0FFFFh + DW 20 + +FilterVolume4 DW 14 + DB 53, 44 + DW 0, 255 + DW 9, 13 + DW 29, 0FFFFh, 26, 26 + DW 0FFFFh, 0FFFFh + DW 20 + + +; ÄÄ MixingRoutines ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixBufferPos DW 0 + +include dma.inc +include mix.inc + +include m32bitm.mix +include m32bitmi.mix +include m32bitmv.mix +include m32bitmf.mix + +ALIGN 2 + +MixFunctionTables Label + +include m32bitm.inc +include m32bitmi.inc +include m32bitmv.inc +include m32bitmf.inc +include mnomix.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +RelocationTable Label Word + DW Offset DriverSegment1, Offset DriverSegment2 + DW Offset DriverSegment3, Offset DriverSegment4 + DW Offset DriverSegment5, Offset DriverSegment6 + DW Offset DriverSegment7, Offset DriverSegment8 + DW 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SBOut ; AL = data + ; DX = 2xCh + + Push AX + +SBOut1: + In AL, DX + Test AL, AL + JS SBOut1 + + Pop AX + Out DX, AL + + Ret + +EndP SBOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SBIn ; DX = 2xEh, returns AL + +SBIn1: + In AL, DX + Test AL, AL + JNS SBIn1 + + Add DL, 0Ah-0Eh ; DX = 2xAh -> Data read port + In AL, DX + Add DL, 0Eh-0Ah + + Ret + +EndP SBIn + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectMMX + + Trace "Detecting MMX - CPUID Check" + + PushFD + Pop EAX + Mov EBX, EAX + Xor EAX, 00200000h + Push EAX + PopFD + PushFD + Pop EAX + Cmp EAX, EBX + JZ DetectMMXFail + + Trace "CPUID - Check OK" + + Mov EAX, 1 + DB 0Fh, 0A2h ; CPUID + Test EDX, 800000h + JZ DetectMMXFail + + Trace "MMX Detected" + + ClC + Ret + +DetectMMXFail: + Trace "MMX Not Detected" + + StC + Ret + +EndP DetectMMX + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectUART ; Given DX = Port + +; From SB-DevKit + + ClI + + Inc DX + Xor CX, CX + +DetectUART1: + In AL, DX + Test AL, 40h ; Ready for output + LoopNZ DetectUART1 + JNZ DetectUARTError + + Mov AL, 0FFh ; Reset! + Out DX, AL + + Xor CX, CX + +DetectUART2: + In AL, DX + Test AL, 80h + JNZ DetectUART3 + + Dec DX + In AL, DX + Inc DX + Cmp AL, 0FEh + JE DetectUART4 + +DetectUART3: + Loop DetectUART2 + +DetectUARTError: + StI + StC + Ret + +DetectUART4: ; Now to shove it into 'intelligent' mode. + Xor CX, CX + +DetectUART5: + In AL, DX + Test AL, 40h + LoopNZ DetectUART5 + JNZ DetectUARTError + + Mov AL, 3Fh ; Intelligent mode! + Out DX, AL + +DetectUART6: + Xor CX, CX + +DetectUART7: + In AL, DX + Test AL, 80h + JNZ DetectUART8 + + Dec DX + In AL, DX + Inc DX + Cmp AL, 0FEh + JE DetectUART9 + +DetectUART8: + Loop DetectUART7 + + Jmp DetectUARTError + +DetectUART9: + StI + ClC + Ret + +EndP DetectUART + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReinitUART + + Mov DX, MIDIPort + Test DX, DX + JZ ReinitUART1 + + Call DetectUART + +ReinitUART1: + Ret + +EndP ReinitUART + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetUART + + Mov DX, MIDIPort + Test DX, DX + JZ ResetUART1 + + Inc DX + + Mov AL, 0FFh + Out DX, AL + +ResetUART1: + Ret + +EndP ResetUART + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixMode Far + + Push CS + Pop ES + Mov DI, Offset MixMode + + Ret + +EndP GetMixMode + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixMode Far + + Mov AX, [SI+22] + + ClI + + Mov CS:MixMode, AX + + Mov BX, 60 + Mul BX + Mov CS:MixModeOffset, AX + + StI + + Mov AX, 1 + Ret + +EndP SetMixMode + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SBGetRegister + + Out DX, AL + Inc DX + In AL, DX + Dec DX + + Ret + +EndP SBGetRegister + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetSBMixConst ; Work out value.. and nearest + ; mixspeed value. + + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, CmdLineMixSpeed + Mov CX, MixSpeed + Test AX, AX + JZ GetSBMixConst1 + + Mov CX, 45454 + Cmp AX, CX + JA GetSBMixConst1 + + Mov CX, 12000 + Cmp AX, CX + JB GetSBMixConst1 + + Mov CX, AX + +GetSBMixConst1: + Mov AX, 1000 + Mul AX + Div CX + Mov AH, AL + Neg AH + Mov SBMixConst, AH + + MovZX BX, AL + Mov AX, 1000 + Mul AX + Div BX + Mov MixSpeed, AX + + FNInit + FILd DWord Ptr [MixSpeed] + FMul FreqMultiplier + FStP FreqMultiplier + + Mov BX, 12000 + Xor DX, DX + Div BX + Mov FourierBufferStepOffset, AX + Mov FourierBufferStepFractional, DX + + Pop DS + PopA + Ret + +EndP GetSBMixConst + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetDSP Far ; AX = Port + + Push AX + Push CX + Push DX + + Mov DX, AX + Add DL, 6 + Mov AL, 1 + Out DX, AL + + In AL, DX + In AL, DX + In AL, DX + In AL, DX + + Xor AL, AL + Out DX, AL + + Add DL, 8 + Mov CX, 200 + +ResetDSP1: + In AL, DX + Test AL, AL + JS ResetDSP2 + Loop ResetDSP1 + Jmp ResetDSP3 + +ResetDSP2: + Sub DL, 4 + In AL, DX + Cmp AL, 0AAh + JE ResetDSP4 + Add DL, 4 + Loop ResetDSP1 + +ResetDSP3: + StC + +ResetDSP4: + Pop DX + Pop CX + Pop AX + Ret + +EndP ResetDSP + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetDSPIRQ + + Mov DX, CS:BasePort + Add DL, 4 + Mov AH, CS:DSPIRQValue + Mov AL, 80h + Out DX, AX + + Ret + +EndP ResetDSPIRQ + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetDSPDMA + + Mov DX, CS:BasePort + Add DL, 4 + Mov AH, CS:DSPDMAValue + Mov AL, 81h + Out DX, AX + + Ret + +EndP ResetDSPDMA + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far + + Push CS + Pop DS + Assume DS:Driver + + Mov Forced, AL + + Cmp BX, 217h + JAE DetectCardUseDriver + + Mov CX, DS + ShL ECX, 16 + Mov CX, Offset DefaultDriverName + +DetectCardUseDriver: + Mov DriverName, ECX + + Call DetectMMX + JC DetectCardFailure + + Mov AX, BasePort + Cmp AX, 0FFFFh + JE DetectCard1 + + Cmp AX, 210h + JB DetectCard9 + Cmp AX, 280h + JA DetectCard9 + + Call ResetDSP + JNC DetectCard2 + + Ret + +DetectCard1: + Mov AX, 210h + +DetectCard2: + Call ResetDSP + JNC DetectCard3 + Add AL, 10h + Cmp AL, 80h + JBE DetectCard2 + +DetectCard9: + StC + Ret + +DetectCard3: ; OK... DSP found. + ; Get DSP version + Mov BasePort, AX + + Mov DX, AX + Add DL, 0Ch ; 2xCh -> Data ready to send... + +DetectCardOuputLoop1: + In AL, DX + Test AL, AL + JS DetectCardOuputLoop1 + + Mov AL, 0E1h ; Get DSP version command + Out DX, AL + + Add DL, 0Eh-0Ch ; DX = 2xEh -> Data available status + + Call SBIn + Mov AH, AL ; AH = Major version number + Call SBIn ; AL = Minor version number + + Cmp AH, 4 ; SB DSP = 4.00+ + JAE DetectCard5 + +DetectCard4: + StC + Ret + +DetectCard5: + Mov DSPVersion, AX + + Add DL, 04h-0Eh ; 2x4h = Mixer index port + Mov AL, 80h ; IRQ select + Out DX, AL + Inc DL ; 2x5h = Mixer data port + + In AL, DX + + Dec DL + + Mov DSPIRQValue, AL + ; OK.. now get IRQ, or set IRQ + Mov BX, IRQ + Cmp BX, 0FFFFh + JE DetectCardIRQ1 + Cmp Forced, 0 + JE DetectCardIRQ1 + + Mov AH, 11h + Cmp BL, 2 + JE SetCardIRQ1 + Cmp BL, 9 + JE SetCardIRQ1 + + Mov AH, 12h + Cmp BL, 5 + JE SetCardIRQ1 + + Mov AH, 14h + Cmp BL, 7 + JE SetCardIRQ1 + + Mov AH, 18h + Cmp BL, 10 + JE SetCardIRQ1 + + StC + Ret + +SetCardIRQ1: + Mov AL, 80h + Out DX, AL + Inc DL + Mov AL, AH + Out DX, AL + Dec DL + Jmp DetectCard6 + +DetectCardIRQ1: + Mov BX, 2 + Test AL, 1 + JNZ DetectCardIRQ2 + + Mov BL, 5 + Test AL, 2 + JNZ DetectCardIRQ2 + + Mov BL, 7 + Test AL, 4 + JNZ DetectCardIRQ2 + + Mov BL, 10 + Test AL, 8 + JNZ DetectCardIRQ2 + + StC + Ret + +DetectCardIRQ2: + Cmp IRQ, 0FFFFh + JE DetectCardIRQ3 + + Cmp BX, IRQ + JE DetectCard6 + +DetectCardFailure: + StC + Ret + +DetectCardIRQ3: + Mov IRQ, BX + +DetectCard6: ; Detect DMA + Mov AL, 81h ; DMA select + Out DX, AL + Inc DL + In AL, DX ; AL = DMA + Dec DL + + Mov DSPDMAValue, AL + + Mov BX, DMA + Cmp BX, 0FFFFh + JE DetectCardDMA1 + Cmp Forced, 0 + JE DetectCardDMA1 + + Mov CL, 1 + Cmp BX, 1 + JB SetCardDMA1 + + Mov CL, 2 + JE SetCardDMA1 + + Cmp BX, 3 + JB DetectCard7 + + Mov CL, 8 + JE DetectCard7 + + Mov CL, 20h + Cmp BX, 5 + JB DetectCard7 + JE SetCardDMA1 + + Mov CL, 80h + Cmp BX, 7 + JA DetectCard7 + JE SetCardDMA1 + + Mov CL, 40h + +SetCardDMA1: + And AL, 0Bh + Test CL, 0Bh + JZ SetCardDMA4 + + Xor AL, AL + +SetCardDMA4: + Or CL, AL + + Mov AL, 81h + Out DX, AL + Inc DL + Mov AL, CL + Out DX, AL + Jmp DetectCard7 + +DetectCardDMA1: + Mov BX, 5 + Test AL, 20h + JNZ DetectCardDMA2 + + Inc BL + Test AL, 40h + JNZ DetectCardDMA2 + + Inc BL + Test AL, 80h + JNZ DetectCardDMA2 + + Mov BL, 0 + Test AL, 1 + JNZ DetectCardDMA2 + + Inc BL + Test AL, 2 + JNZ DetectCardDMA2 + + Add BL, 2 + Test AL, 8 + JNZ DetectCardDMA2 + +DetectCard8: + Call ResetDSPIRQ + StC + Ret + +DetectCardDMA2: + Cmp DMA, 0FFFFh + JE DetectCardDMA3 + + Cmp BX, DMA + JNE DetectCard8 + +DetectCardDMA3: + Mov DMA, BX + +DetectCard7: + Mov EAX, 'Jeff' + + ClC + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include mmxmsam.inc +include fourier.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc AckIRQ + Assume DS:Driver + + Mov AL, 20h + Cmp CS:IRQ, 7 + JBE AckIRQ1 + + Out 0A0h, AL + +AckIRQ1: + Out 20h, AL + Ret + +EndP AckIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc CheckMIDI + + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Xor BX, BX + Mov DX, MIDIPort + + Mov BL, [MIDIBufferTail] + Test DX, DX + JZ CheckMIDIEnd + + Inc DX + Mov CX, 0FFFFh + +CheckMIDIAgain: + In AL, DX + + Test AL, 80h + LoopNZ CheckMIDIAgain + + Dec DX + In AL, DX + + Cmp AL, 0F0h + JAE CheckMIDIEnd + + Inc BL + Cmp BL, MIDIBufferHead + JE CheckMIDIEnd + + Mov [MIDIBuffer+BX], AL + Mov [MIDIBufferTail], BL +; Jmp CheckMIDIAgain + +CheckMIDIEnd: + Pop DS + Ret + +EndP CheckMIDI + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SB16IRQHandler + + PushAD + Push DS + Push ES + + CLD + +SBIRQAgain: + Mov AX, CS + Mov DS, AX + Assume DS:Driver + + Mov DX, BasePort + Add DL, 4 ; Mixer Port + Mov AL, 82h + Out DX, AL + Inc DL ; DX = BasePort+5 + In AL, DX + +Comment ~ + Test AL, 1 + JZ SB8BitDigitalInterruptEnd + +SB8BitDigitalInterrupt: + Push AX + Add DL, 0Eh-5 + In AL, DX + Pop AX + +SB8BitDigitalInterruptEnd: + + ~ + Test AL, 4 + JZ SBMIDIInterruptEnd + + Push AX + Call CheckMIDI + Pop AX + +SBMIDIInterruptEnd: + Test AL, 2 + JNZ SBDigitalInterrupt + + Call AckIRQ + Jmp SBIRQEnd + +SBDigitalInterrupt: + FNSave [FPSave] + + Mov DX, BasePort + Add DL, 0Fh + In AL, DX ; 16-bit IRQ ack. + + Call AckIRQ + + Mov AX, MixBufferPos + Mov BX, AX + Mul DMASize + Cmp AX, DMABUFFERLENGTH + JB SB16IRQHandler2 + + Xor AX, AX + Xor BX, BX + +SB16IRQHandler2: + Inc BX + Mov MixBufferPos, BX + + + ; OK... time to get next block + ; Check whether stereo thing is on.. + ; + LES DI, [ActualDMAPtr] + Mov BX, DMASize ; BX = bytes required + Add DI, AX + ShR BX, 1 + ; BX = samples required + Call SaveEMSPageFrame + + Cmp MixTransferRemaining, 0 + JNE SB16IRQHandler4 + Assume DS:Nothing + +SB16IRQHandler3: + Push BX + Push CX + Push BP + Push ES + Push DI + + Call Update + Call MixSamples + Call UpdateFourierBuffer + + Pop DI + Pop ES + Pop BP + Pop CX + Pop BX + +SB16IRQHandler4: + Mov DS, MixSegment + Mov SI, MixTransferOffset + Mov DX, BX ; DX = samples to transfer + Cmp DX, MixTransferRemaining + JBE SB16IRQHandler5 + + Mov DX, MixTransferRemaining + +SB16IRQHandler5: + +include mmxtrans.inc + + Sub MixTransferRemaining, DX ; } Memory write + Sub BX, DX + JNZ SB16IRQHandler3 + + Mov MixTransferOffset, SI ; } Memory write + + Call RestoreEMSPageFrame + + FNRstor [CS:FPSave] + +SBIRQEnd: + Pop ES + Pop DS + PopAD + IRet + +EndP SB16IRQHandler + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + + PushAD + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Add DI, Offset IRQData + Mov BX, [DI] + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset SB16IRQHandler + + XChg [ES:BX], EAX + Mov OldIRQHandler, EAX + + Mov AX, IMR + And AX, [DI+2] + + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Pop ES + Pop DS + PopAD + + Ret + +EndP SetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIRQ + + PushAD + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Mov BX, [IRQData+DI] + + Mov EAX, OldIRQHandler + Mov [ES:BX], EAX + + Pop ES + Pop DS + PopAD + + Ret + +EndP ResetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StartSB16 ; + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + ; Setup DMA + Mov BX, MixSegment + Mov AX, 80 + Mov DX, DMA + Mov DI, DMABUFFERLENGTH + Call SetDMA + + LES DI, ActualDMAPtr + Xor AX, AX + Mov CX, DMABUFFERLENGTH/2 + Rep StosW + + Mov MixBufferPos, 0 + Mov MixTransferRemaining, 0 + + Mov DX, BasePort + Add DL, 0Ch + + Mov AL, 0D1h ; turn on speaker + Call SBOut + + Mov AL, 40h ; time constant + Call SBOut + Mov AL, SBMixConst + Call SBOut + + Mov AL, 0B6h ; 16 bit, DAC + Call SBOut + Mov AL, Stereo + ShL AL, 5 + Or AL, 10h + Call SBOut + + Mov AX, DMASize + ShR AX, 1 + Dec AX + + Call SBOut ; DMALength, Lo + Mov AL, AH + Call SBOut + + Pop ES + Pop DS + PopA + + Ret + + Assume DS:Nothing + +EndP StartSB16 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixerRegisters + + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Pop DS + + Ret + +EndP GetMixerRegisters + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + Mov SI, Offset RelocationTable + +RelocationFix: + LodsW + Test AX, AX + JZ RelocationEnd + Mov BX, AX + Mov [BX], DS + Jmp RelocationFix + +RelocationEnd: + Call GetEMSPageFrame + Mov EMSPageFrame, AX + + In AL, 0A1h + Mov AH, AL + In AL, 21h + Mov IMR, AX + + Mov DX, BasePort + Add DL, 4 + + Mov AL, 30h + Call SBGetRegister + ShR AL, 3 + Mov VolumeTable, AL + + Mov AL, 31h + Call SBGetRegister + ShR AL, 3 + Mov [VolumeTable+1], AL + + Mov AL, 44h + Call SBGetRegister + ShR AL, 4 + Mov [VolumeTable+2], AL + + Mov AL, 45h + Call SBGetRegister + ShR AL, 4 + Mov [VolumeTable+3], AL + + Mov AL, 46h + Call SBGetRegister + ShR AL, 4 + Mov [VolumeTable+4], AL + + Mov AL, 47h + Call SBGetRegister + ShR AL, 4 + Mov [VolumeTable+5], AL + + Call GetSBMixConst + + ; Parags to allocate = (8/(.4*31*16))*MixSpeed + ; = .04032258*MixSpeed = (65536*.04032258*MixSpeed) / 65536 + + Mov AX, 2643 + Mul MixSpeed + Add AX, 0FFFFh + AdC DX, 5+(DMABUFFERLENGTH*2)/16+(FOURIERBUFFERLENGTH*2)/16 + Mov BX, DX + + ; Allocate MixSegment first + Mov AH, 48h + + Int 21h + JNC InitSound1 + +InitSoundNoMemory: + Mov SI, Offset SB16NoMemoryMsg + Ret + +InitSound1: + Mov MixSegment, AX + Add AX, DX + Sub AX, (FOURIERBUFFERLENGTH*2)/16 + Mov FourierSegment, AX + + Call SetIRQ + Call GetTempo + Call SetTempo + + Mov DX, 330h + Call DetectUART + JC DetectMIDI1 + + Mov MIDIPort, 330h + Jmp DetectMIDIEnd + +DetectMIDI1: + Mov DX, 300h + Call DetectUART + JC DetectMIDIEnd + + Mov MIDIPort, 300h + +DetectMIDIEnd: + Call CalculateFilterCoefficients + + Mov SI, Offset SB16Msg + + Mov AX, BasePort + Mov BX, IRQ + Mov CX, DMA + + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, BasePort + Call ResetDSP + + Call ResetUART + Call ResetIRQ + + ; Delay.. + Mov DX, BasePort + Add DL, 0Ch + + Mov CX, 1000 +ReInitSound1: + In AL, DX + Loop ReInitSound1 + + Call SetIRQ + Call ReinitUART + + Mov SI, Offset ReInitMsg + Mov BX, 40 + Call SetInfoLine + + Mov AL, Stereo + Call SetStereo + + Pop ES + Pop DS + PopA + + Ret + +EndP ReInitSound + Assume DS:Nothing + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Call GotoHomeDirectory + + Mov DS, Word Ptr [CS:DriverName+2] + Mov DX, Word Ptr [CS:DriverName] + + Mov AX, 3D02h ; Read write access + Int 21h + + Push CS + Pop DS + Assume DS:Driver + + JC SaveConfig2 + + Mov BX, AX + + Mov AX, 4200h + Xor CX, CX + Mov DX, Offset CONFIGURATIONOFFSET + Int 21h + JC SaveConfig1 + + Mov AH, 40h + Mov CX, CONFIGSIZE + Mov DX, Offset MixMode + Int 21h + +SaveConfig1: + Mov AH, 3Eh + Int 21h + +SaveConfig2: + Mov DX, CS:BasePort + Add DL, 0Ch + + Mov AL, 0D9h + Call SBOut + + Call ResetUART + + Mov AX, BasePort + Call ResetDSP + + Call ResetDSPDMA + Call ResetDSPIRQ + + Mov AX, IMR + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Mov AX, MixSegment + Test AX, AX + JZ UnInitSound1 + + Mov ES, AX + Mov AH, 49h ; Release MixSegment + Int 21h + + Call ResetIRQ + +UnInitSound1: + Ret + +EndP UnInitSound + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + Push CS + Pop DS + Assume DS:Driver + +Poll1: + Call [UARTBufferEmpty] + JNC PollEnd + + Xor BX, BX + + ClI + + Mov BL, MIDIBufferHead + Cmp BL, MIDIBufferTail + JZ PollEnd ; Nothing in queue + + Inc BL + Mov AL, [MIDIBuffer+BX] + Mov MIDIBufferHead, BL + + Call [UARTSend] + Jmp Poll1 + +PollEnd: + StI + + Ret + +EndP Poll + Assume DS:Nothing + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Push AX + Push BX + Push DX + + Push BX + + Mov AX, MixSpeed + Mov BX, AX + Xor DX, DX + + ShL AX, 1 + RCL DX, 1 ; DX:AX = Mixspeed*2 + + ShR BX, 1 ; BX = Mixspeed/2 + + Add AX, BX + AdC DX, 0 ; DX:AX = Mixspeed*2.5 + + Pop BX ; BX = tempo + Div BX + + Mov BytesToMix, AX + + Pop DX + Pop BX + Pop AX + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + Mov CS:MixVolume, AX + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Jmp CS:RecalculateAllVolumes + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Cmp CS:MixSegment, 0 + JE SetStereo1 + + Mov CS:Stereo, AL + Mov AX, CS:BasePort + Call ResetDSP + + Call StartSB16 + +SetStereo1: + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include loadsam.inc + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset SB16ScreenList + + ClC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far ; Returns AX, given DI + + Xor AH, AH + Mov AL, [CS:VolumeTable+DI] + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +TempVariable DW 0 +Const1 DD 3F800000h + +Proc GetFilterFrequency ; Given AL= Freq + Assume DS:Driver + + ShL AX, 8 + Mov TempVariable, AX + FILD TempVariable + + FMul FreqParameterMultiplier ; -i/(24*256) + FLd ST + FRndInt + FSub ST(1), ST + FXCh + F2XM1 + FLd1 + FAdd + FScale ; = 2^(i/24*256) + FMul FreqMultiplier ; = r + + FLd1 ; 1, c + FAdd ST, ST(1) ; 1+c, c + FDivR Const1 ; 1/(1+c), c + FSt DWord Ptr [SI] + FMul + FStP DWord Ptr [SI+4] + FStP ST + + Ret + +EndP GetFilterFrequency + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Const1On16 DD 3D000000h ; actually 1 on 32 + +Proc CalculateFilterCoefficients + Assume DS:Driver + + PushA + + FNInit + FLdCW NewControlWord + + Mov AL, [VolumeTable+6] + Mov SI, Offset FilterCoefficients + ShR AL, 1 + Call GetFilterFrequency + + Mov AL, [VolumeTable+7] ; FilterFrequency1 + Add SI, 8 + Call GetFilterFrequency + + Mov AL, [VolumeTable+8] ; FilterFrequency1 + Add SI, 8 + Call GetFilterFrequency + + Mov AL, [VolumeTable+9] ; FilterFrequency1 + Add SI, 8 + Call GetFilterFrequency + +; Now volumes + Mov SI, Offset VolumeTable+10 + Mov DI, Offset FilterVolumes + Xor AX, AX + Mov CX, 4 + +FilterVolumeLoop1: + LodSB + Mov TempVariable, AX + FILD TempVariable + FMul Const1On16 + FStP DWord Ptr [DI] + + Add DI, 4 + Loop FilterVolumeLoop1 + + PopA + Ret + +EndP CalculateFilterCoefficients + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far ; Given AX, DI + + Push DS + Push DX + + Push CS + Pop DS + Assume DS:Driver + + Mov [VolumeTable+DI], AL + + Cmp DI, 9 + JA SetVariable3 + + Cmp DI, 6 + JB SetVariable1 + + JE SetVariable2 + + Cmp AL, [VolumeTable+DI-1] + JAE SetVariable2 + + Mov AL, [VolumeTable+DI-1] + Mov [VolumeTable+DI], AL + +SetVariable2: + Cmp DI, 9 + JAE SetVariable3 + + Cmp AL, [VolumeTable+DI+1] + JBE SetVariable3 + + Mov AL, [VolumeTable+DI+1] + Mov [VolumeTable+DI], AL + +SetVariable3: + Call CalculateFilterCoefficients + Jmp SetVariableEnd + +SetVariable1: + Mov DX, BasePort + Add DL, 4 + Mov AL, 30h + Mov AH, [VolumeTable] + ShL AH, 3 + Out DX, AX + + Mov AL, 31h + Mov AH, [VolumeTable+1] + ShL AH, 3 + Out DX, AX + + Mov AL, 44h + Mov AH, [VolumeTable+2] + ShL AH, 4 + Out DX, AX + + Mov AL, 45h + Mov AH, [VolumeTable+3] + ShL AH, 4 + Out DX, AX + + Mov AL, 46h + Mov AH, [VolumeTable+4] + ShL AH, 4 + Out DX, AX + + Mov AL, 47h + Mov AH, [VolumeTable+5] + ShL AH, 4 + Out DX, AX + +SetVariableEnd: + Pop DX + Pop DS + Ret + +EndP SetVariable + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UARTOut + + Push CX + Push DX + Mov DX, CS:MIDIPort + Test DX, DX + JZ UARTOutEnd + + Push AX + Xor CX, CX + Inc DX + +UARTOut1: + In AL, DX + Test AL, 40h + LoopNZ UARTOut1 + + Pop AX + JNZ UARTOutEnd + + Dec DX + Out DX, AL + +UARTOutEnd: + Pop DX + Pop CX + + Ret + +EndP UARTOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +InterpretState DB 0 +InterpretType DB 0 + +Proc SendUARTOut Far ; Local interpreter activated with 0F0h 0F0h. + + Mov AH, CS:InterpretState + Cmp AH, 2 + JB SendUARTOut1 + +; In interpreter. + JE SendUARTOut3 + +; Have InterpretType, now get parameter, then return to normal. + + Cmp AL, 7Fh + JA SendUARTOut4 + + Push BX + + Mov BL, CS:InterpretType ; Want BX = InterpretType*64+Channel + ; + ShL BX, 6 + Add BL, [DI+20h] + And BX, 127 + Mov [CS:FilterParameters+BX], AL + + Pop BX + + Test SI, SI + JZ SendUARTOut4 + + Or Byte Ptr [SI], 64 + +SendUARTOut4: + Mov CS:InterpretState, 0 + Ret + +SendUARTOut3: + Cmp AL, 2 + JAE SendUARTOut4 + + Mov CS:InterpretType, AL + Jmp SendUARTOutStateInc + +SendUARTOut1: + Cmp AL, 0F0h + JNE SendUARTOut2 + +SendUARTOutStateInc: + Inc CS:InterpretState + Ret + +SendUARTOut2: + Test AH, AH + JZ SendUARTOutEnd + + Push AX + Mov AL, 0F0h + Call UARTOut + Pop AX + Mov CS:InterpretState, 0 + +SendUARTOutEnd: + Cmp AL, 0FCh + JE ResetFilters + Cmp AL, 0FAh + JE ResetFilters + + Cmp AL, 0FFh + JNE SendUARTOutNoClear + +ResetFilters: + PushA + Push ES + + Push CS + Pop ES + + Mov DI, Offset FilterParameters + Mov CX, 64 + Mov AL, 7Fh + Rep StosB + Mov CX, 64 + Xor AX, AX + Rep StosB + + Pop ES + PopA + +SendUARTOutNoClear: + Call UARTOut + Ret + +EndP SendUARTOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetWaveForm Far ; Given ES:DI = destination + Assume DS:Nothing ; want 2048 samples. + + PushA + Push DS + + Mov DS, FourierSegment + Mov SI, FourierBufferStart + Mov CX, 2048 + +GetWaveForm1: + MovsW + And SI, (FOURIERBUFFERLENGTH*2)-1 + Loop GetWaveForm1 + + Pop DS + PopA + + Ret + +EndP GetWaveForm + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. + +StopAfterPlay DW 0 +DefaultChannels DW 128 + DW 7 ; MIDI, hiqual + DW 4 Dup (0) + + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + + DW Offset SendUARTOut + + DW Offset GetWaveform + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/SB16MMXB.ASM b/SoundDrivers/SB16MMXB.ASM new file mode 100755 index 0000000..15607d8 --- /dev/null +++ b/SoundDrivers/SB16MMXB.ASM @@ -0,0 +1,2265 @@ + + + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc +include mmx.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;********************************** + +TRACEENABLED = 0 +CREATENEWLOGFILE = 1 + +include debug.inc + +STEREOENABLED EQU 1 +DMABUFFERLENGTH EQU 4096 +MIXRESOLUTION EQU 32 ; 32 bit mixing for the SB16 +OUTPUTFILTERENABLED EQU 1 +FOURIERBUFFERLENGTH EQU 2048 ; 2048 samples + +FPSave DB 128 Dup (0) + +SB16Msg DB "Sound Blaster 16 MMX", 13 + DB "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, DMA ", 0FDh, "D", 0 + +SB16NoMemoryMsg DB "Sound Blaster 16 MMX", 13 + DB "Error: Insufficient memory", 0 + +ReinitMsg DB "Sound Blaster 16 reinitialised", 0 + +DefaultDriverName DB "ITSB16.MMX", 0 +DriverName DD 0 + +DSPVersion DW 0 +DSPIRQValue DB 0 +DSPDMAValue DB 0 +Forced DB 0 +Stereo DB 0 +MixVolume DW 0 + +BytesToMix DW 1000 +SBMixConst DB 0 + +MixSegment DW 0 +FourierSegment DW 0 + +MixTransferOffset DW 0 +MixTransferRemaining DW 0 + +CONFIGURATIONOFFSET EQU $+128 +CONFIGSIZE EQU 20 +MixMode DW 0 +MixModeOffset DW 0 +DMASize DW 2048 +VolumeTable DB 6 Dup (0) + DB 0, 16, 96, 127 + DB 0, 0, 0, 0 + +IMR DW 0 +OldIRQHandler DD 0 + +MIDIPort DW 0 +MIDIBuffer DB 256 Dup (0) +MIDIBufferHead DB 0 +MIDIBufferTail DB 0 + +IRQData Label Word + DW 20h, 1111111111111110b ; IRQ 0 + DW 24h, 1111111111111101b ; IRQ 1 + DW 28h, 1111110111111011b ; IRQ 2 + DW 2Ch, 1111111111110111b ; IRQ 3 + DW 30h, 1111111111101111b ; IRQ 4 + DW 34h, 1111111111011111b ; IRQ 5 + DW 38h, 1111111110111111b ; IRQ 6 + DW 3Ch, 1111111101111111b ; IRQ 7 + DW 1C0h, 1111111011111011b ; IRQ 8 + DW 1C4h, 1111110111111011b ; IRQ 9 + DW 1C8h, 1111101111111011b ; IRQ 10 + DW 1CCh, 1111011111111011b ; IRQ 11 + DW 1D0h, 1110111111111011b ; IRQ 12 + DW 1D4h, 1101111111111011b ; IRQ 13 + DW 1D8h, 1011111111111011b ; IRQ 14 + DW 1DCh, 0111111111111011b ; IRQ 15 + + +;********************************** + +SB16ScreenList Label + DW 8 + DW Near Ptr IdleFunctionList + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr SB16HeaderLine + + DW Near Ptr VolumeText + DW Near Ptr VolumeBox1 + DW Near Ptr VolumeBox2 + + DW Near Ptr DriverText + + DW Near Ptr MasterVolumeLeft ; 8 + DW Near Ptr MasterVolumeRight ; 9 + DW Near Ptr TrebleVolumeLeft ; 10 + DW Near Ptr TrebleVolumeRight ; 11 + DW Near Ptr BassVolumeLeft ; 12 + DW Near Ptr BassVolumeRight ; 13 + + DW Near Ptr MixModeText + DW Near Ptr MixModeButton1 ; 15 + DW Near Ptr MixModeButton2 ; 16 + DW Near Ptr MixModeButton3 ; 17 + DW Near Ptr MixModeButton4 ; 18 + + DW Near Ptr FrequencyText + + DW Near Ptr FilterText ; 20 + DW Near Ptr FilterBox1 + DW Near Ptr FilterBox2 + + DW Near Ptr FilterFrequency1 ; 23 + DW Near Ptr FilterFrequency2 + DW Near Ptr FilterFrequency3 + DW Near Ptr FilterFrequency4 + + DW Near Ptr FilterVolume1 ; 27 + DW Near Ptr FilterVolume2 + DW Near Ptr FilterVolume3 + DW Near Ptr FilterVolume4 + + DW 0 + + +SB16HeaderLine DW 10 + DB "Sound Blaster 16 Driver", 0 + +DriverText DW 1 + DB 31, 48 + DB 21h + DB "Sound Blaster 16 Driver 1.4 for Impulse Tracker", 0 + +VolumeText DW 1 + DB 2, 13 + DB 20h + DB "Master Volume Left", 13 + DB "Master Volume Right", 13 + DB 13 + DB 13 + DB "Treble Left", 13 + DB "Treble Right", 13 + DB "Bass Left", 13 + DB "Bass Right", 13 + DB 0 + +VolumeBox1 DW 0 + DB 21, 12, 27, 15 + DB 25 + +VolumeBox2 DW 0 + DB 14, 16, 18, 21 + DB 25 + +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +IdleFunctionList DD 0 + DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +MasterVolumeLeft DW 9 + DB 22, 13 + DW 0, 31 + DW 9, 0 + DW 0FFFFh, 9, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +MasterVolumeRight DW 9 + DB 22, 14 + DW 0, 31 + DW 9, 1 + DW 8, 10, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +TrebleVolumeLeft DW 9 + DB 15, 17 + DW 0, 15 + DW 9, 2 + DW 9, 11, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +TrebleVolumeRight DW 9 + DB 15, 18 + DW 0, 15 + DW 9, 3 + DW 10, 12, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +BassVolumeLeft DW 9 + DB 15, 19 + DW 0, 15 + DW 9, 4 + DW 11, 13, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +BassVolumeRight DW 9 + DB 15, 20 + DW 0, 15 + DW 9, 5 + DW 12, 15, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +MixModeText DW 1 + DB 2, 23 + DB 20h + DB "Mixing Mode", 0 + +FrequencyText DW 1 + DB 2, 48 + DB 20h + DB "Playback Frequency: ", 0FDh, "DHz", 0 +MixSpeed DW 45454 + DW 0 + +MixModeButton1 DW 2 + DW 13, 16, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment1 DW 0 + DW 0 + DW Offset SetMixMode +DriverSegment2 DW 0 + DB 3, 25, 32, 27, 8 + DB 0 + DB " MMX, Non-Interpolated", 0 + +MixModeButton2 DW 2 + DW 15, 17, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment3 DW 0 + DW 1 + DW Offset SetMixMode +DriverSegment4 DW 0 + DB 3, 28, 32, 30, 8 + DB 0 + DB " MMX, Interpolated", 0 + +MixModeButton3 DW 2 + DW 16, 18, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment5 DW 0 + DW 2 + DW Offset SetMixMode +DriverSegment6 DW 0 + DB 3, 31, 32, 33, 8 + DB 0 + DB " MMX, Volume Ramped", 0 + +MixModeButton4 DW 2 + DW 17, 23, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment7 DW 0 + DW 3 + DW Offset SetMixMode +DriverSegment8 DW 0 + DB 3, 34, 32, 36, 8 + DB 0 + DB " MMX, Filtered", 0 + +FilterText DW 1 + DB 2, 39 + DB 20h + DB "Output Equalizer", 13 + DB 13 + DB " Low Frequency Band", 13 + DB " Med Low Frequency Band", 13 + DB "Med High Frequency Band", 13 + DB " High Frequency Band", 0 + +FilterBox1 DW 0 + DB 25, 40, 47, 45 + DB 25 + +FilterBox2 DW 0 + DB 52, 40, 74, 45 + DB 25 + +FilterFrequency1 DW 14 + DB 26, 41 + DW 0, 127 + DW 9, 6 + DW 18, 24, 27, 27 + DW 0FFFFh, 0FFFFh + DW 20 + +FilterFrequency2 DW 14 + DB 26, 42 + DW 0, 127 + DW 9, 7 + DW 23, 25, 28, 28 + DW 0FFFFh, 0FFFFh + DW 20 + +FilterFrequency3 DW 14 + DB 26, 43 + DW 0, 127 + DW 9, 8 + DW 24, 26, 29, 29 + DW 0FFFFh, 0FFFFh + DW 20 + +FilterFrequency4 DW 14 + DB 26, 44 + DW 0, 127 + DW 9, 9 + DW 25, 0FFFFh, 30, 30 + DW 0FFFFh, 0FFFFh + DW 20 + +FilterVolume1 DW 14 + DB 53, 41 + DW 0, 255 + DW 9, 10 + DW 18, 28, 23, 23 + DW 0FFFFh, 0FFFFh + DW 20 + +FilterVolume2 DW 14 + DB 53, 42 + DW 0, 255 + DW 9, 11 + DW 27, 29, 24, 24 + DW 0FFFFh, 0FFFFh + DW 20 + +FilterVolume3 DW 14 + DB 53, 43 + DW 0, 255 + DW 9, 12 + DW 28, 30, 25, 25 + DW 0FFFFh, 0FFFFh + DW 20 + +FilterVolume4 DW 14 + DB 53, 44 + DW 0, 255 + DW 9, 13 + DW 29, 0FFFFh, 26, 26 + DW 0FFFFh, 0FFFFh + DW 20 + + +; ÄÄ MixingRoutines ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include dmasirq.inc +include mix.inc + +include m32bitm.mix +include m32bitmi.mix +include m32bitmv.mix +include m32bitmf.mix + +ALIGN 2 + +MixFunctionTables Label + +include m32bitm.inc +include m32bitmi.inc +include m32bitmv.inc +include m32bitmf.inc +include mnomix.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +RelocationTable Label Word + DW Offset DriverSegment1, Offset DriverSegment2 + DW Offset DriverSegment3, Offset DriverSegment4 + DW Offset DriverSegment5, Offset DriverSegment6 + DW Offset DriverSegment7, Offset DriverSegment8 + DW 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SBOut ; AL = data + ; DX = 2xCh + + Push AX + +SBOut1: + In AL, DX + Test AL, AL + JS SBOut1 + + Pop AX + Out DX, AL + + Ret + +EndP SBOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SBIn ; DX = 2xEh, returns AL + +SBIn1: + In AL, DX + Test AL, AL + JNS SBIn1 + + Add DL, 0Ah-0Eh ; DX = 2xAh -> Data read port + In AL, DX + Add DL, 0Eh-0Ah + + Ret + +EndP SBIn + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectMMX + + Trace "Detecting MMX - CPUID Check" + + PushFD + Pop EAX + Mov EBX, EAX + Xor EAX, 00200000h + Push EAX + PopFD + PushFD + Pop EAX + Cmp EAX, EBX + JZ DetectMMXFail + + Trace "CPUID - Check OK" + + Mov EAX, 1 + DB 0Fh, 0A2h ; CPUID + Test EDX, 800000h + JZ DetectMMXFail + + Trace "MMX Detected" + + ClC + Ret + +DetectMMXFail: + Trace "MMX Not Detected" + + StC + Ret + +EndP DetectMMX + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectUART ; Given DX = Port + +; From SB-DevKit + + ClI + + Inc DX + Xor CX, CX + +DetectUART1: + In AL, DX + Test AL, 40h ; Ready for output + LoopNZ DetectUART1 + JNZ DetectUARTError + + Mov AL, 0FFh ; Reset! + Out DX, AL + + Xor CX, CX + +DetectUART2: + In AL, DX + Test AL, 80h + JNZ DetectUART3 + + Dec DX + In AL, DX + Inc DX + Cmp AL, 0FEh + JE DetectUART4 + +DetectUART3: + Loop DetectUART2 + +DetectUARTError: + StI + StC + Ret + +DetectUART4: ; Now to shove it into 'intelligent' mode. + Xor CX, CX + +DetectUART5: + In AL, DX + Test AL, 40h + LoopNZ DetectUART5 + JNZ DetectUARTError + + Mov AL, 3Fh ; Intelligent mode! + Out DX, AL + +DetectUART6: + Xor CX, CX + +DetectUART7: + In AL, DX + Test AL, 80h + JNZ DetectUART8 + + Dec DX + In AL, DX + Inc DX + Cmp AL, 0FEh + JE DetectUART9 + +DetectUART8: + Loop DetectUART7 + + Jmp DetectUARTError + +DetectUART9: + StI + ClC + Ret + +EndP DetectUART + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReinitUART + + Mov DX, MIDIPort + Test DX, DX + JZ ReinitUART1 + + Call DetectUART + +ReinitUART1: + Ret + +EndP ReinitUART + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetUART + + Mov DX, MIDIPort + Test DX, DX + JZ ResetUART1 + + Inc DX + + Mov AL, 0FFh + Out DX, AL + +ResetUART1: + Ret + +EndP ResetUART + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixMode Far + + Push CS + Pop ES + Mov DI, Offset MixMode + + Ret + +EndP GetMixMode + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixMode Far + + Mov AX, [SI+22] + + ClI + + Mov CS:MixMode, AX + + Mov BX, 60 + Mul BX + Mov CS:MixModeOffset, AX + + StI + + Mov AX, 1 + Ret + +EndP SetMixMode + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SBGetRegister + + Out DX, AL + Inc DX + In AL, DX + Dec DX + + Ret + +EndP SBGetRegister + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetSBMixConst ; Work out value.. and nearest + ; mixspeed value. + + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, CmdLineMixSpeed + Mov CX, MixSpeed + Test AX, AX + JZ GetSBMixConst1 + + Mov CX, 45454 + Cmp AX, CX + JA GetSBMixConst1 + + Mov CX, 12000 + Cmp AX, CX + JB GetSBMixConst1 + + Mov CX, AX + +GetSBMixConst1: + Mov AX, 1000 + Mul AX + Div CX + Mov AH, AL + Neg AH + Mov SBMixConst, AH + + MovZX BX, AL + Mov AX, 1000 + Mul AX + Div BX + Mov MixSpeed, AX + + FNInit + FILd DWord Ptr [MixSpeed] + FMul FreqMultiplier + FStP FreqMultiplier + + Mov BX, 12000 + Xor DX, DX + Div BX + Mov FourierBufferStepOffset, AX + Mov FourierBufferStepFractional, DX + + Pop DS + PopA + Ret + +EndP GetSBMixConst + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetDSP Far ; AX = Port + + Push AX + Push CX + Push DX + + Mov DX, AX + Add DL, 6 + Mov AL, 1 + Out DX, AL + + In AL, DX + In AL, DX + In AL, DX + In AL, DX + + Xor AL, AL + Out DX, AL + + Add DL, 8 + Mov CX, 200 + +ResetDSP1: + In AL, DX + Test AL, AL + JS ResetDSP2 + Loop ResetDSP1 + Jmp ResetDSP3 + +ResetDSP2: + Sub DL, 4 + In AL, DX + Cmp AL, 0AAh + JE ResetDSP4 + Add DL, 4 + Loop ResetDSP1 + +ResetDSP3: + StC + +ResetDSP4: + Pop DX + Pop CX + Pop AX + Ret + +EndP ResetDSP + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetDSPIRQ + + Mov DX, CS:BasePort + Add DL, 4 + Mov AH, CS:DSPIRQValue + Mov AL, 80h + Out DX, AX + + Ret + +EndP ResetDSPIRQ + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetDSPDMA + + Mov DX, CS:BasePort + Add DL, 4 + Mov AH, CS:DSPDMAValue + Mov AL, 81h + Out DX, AX + + Ret + +EndP ResetDSPDMA + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far + + Push CS + Pop DS + Assume DS:Driver + + Mov Forced, AL + + Cmp BX, 217h + JAE DetectCardUseDriver + + Mov CX, DS + ShL ECX, 16 + Mov CX, Offset DefaultDriverName + +DetectCardUseDriver: + Mov DriverName, ECX + + Call DetectMMX + JC DetectCardFailure + + Mov AX, BasePort + Cmp AX, 0FFFFh + JE DetectCard1 + + Cmp AX, 210h + JB DetectCard9 + Cmp AX, 280h + JA DetectCard9 + + Call ResetDSP + JNC DetectCard2 + + Ret + +DetectCard1: + Mov AX, 210h + +DetectCard2: + Call ResetDSP + JNC DetectCard3 + Add AL, 10h + Cmp AL, 80h + JBE DetectCard2 + +DetectCard9: + StC + Ret + +DetectCard3: ; OK... DSP found. + ; Get DSP version + Mov BasePort, AX + + Mov DX, AX + Add DL, 0Ch ; 2xCh -> Data ready to send... + +DetectCardOuputLoop1: + In AL, DX + Test AL, AL + JS DetectCardOuputLoop1 + + Mov AL, 0E1h ; Get DSP version command + Out DX, AL + + Add DL, 0Eh-0Ch ; DX = 2xEh -> Data available status + + Call SBIn + Mov AH, AL ; AH = Major version number + Call SBIn ; AL = Minor version number + + Cmp AH, 4 ; SB DSP = 4.00+ + JAE DetectCard5 + +DetectCard4: + StC + Ret + +DetectCard5: + Mov DSPVersion, AX + + Add DL, 04h-0Eh ; 2x4h = Mixer index port + Mov AL, 80h ; IRQ select + Out DX, AL + Inc DL ; 2x5h = Mixer data port + + In AL, DX + + Dec DL + + Mov DSPIRQValue, AL + ; OK.. now get IRQ, or set IRQ + Mov BX, IRQ + Cmp BX, 0FFFFh + JE DetectCardIRQ1 + Cmp Forced, 0 + JE DetectCardIRQ1 + + Mov AH, 11h + Cmp BL, 2 + JE SetCardIRQ1 + Cmp BL, 9 + JE SetCardIRQ1 + + Mov AH, 12h + Cmp BL, 5 + JE SetCardIRQ1 + + Mov AH, 14h + Cmp BL, 7 + JE SetCardIRQ1 + + Mov AH, 18h + Cmp BL, 10 + JE SetCardIRQ1 + + StC + Ret + +SetCardIRQ1: + Mov AL, 80h + Out DX, AL + Inc DL + Mov AL, AH + Out DX, AL + Dec DL + Jmp DetectCard6 + +DetectCardIRQ1: + Mov BX, 2 + Test AL, 1 + JNZ DetectCardIRQ2 + + Mov BL, 5 + Test AL, 2 + JNZ DetectCardIRQ2 + + Mov BL, 7 + Test AL, 4 + JNZ DetectCardIRQ2 + + Mov BL, 10 + Test AL, 8 + JNZ DetectCardIRQ2 + + StC + Ret + +DetectCardIRQ2: + Cmp IRQ, 0FFFFh + JE DetectCardIRQ3 + + Cmp BX, IRQ + JE DetectCard6 + +DetectCardFailure: + StC + Ret + +DetectCardIRQ3: + Mov IRQ, BX + +DetectCard6: ; Detect DMA + Mov AL, 81h ; DMA select + Out DX, AL + Inc DL + In AL, DX ; AL = DMA + Dec DL + + Mov DSPDMAValue, AL + + Mov BX, DMA + Cmp BX, 0FFFFh + JE DetectCardDMA1 + Cmp Forced, 0 + JE DetectCardDMA1 + + Mov CL, 1 + Cmp BX, 1 + JB SetCardDMA1 + + Mov CL, 2 + JE SetCardDMA1 + + Cmp BX, 3 + JB DetectCard7 + + Mov CL, 8 + JE DetectCard7 + + Mov CL, 20h + Cmp BX, 5 + JB DetectCard7 + JE SetCardDMA1 + + Mov CL, 80h + Cmp BX, 7 + JA DetectCard7 + JE SetCardDMA1 + + Mov CL, 40h + +SetCardDMA1: + And AL, 0Bh + Test CL, 0Bh + JZ SetCardDMA4 + + Xor AL, AL + +SetCardDMA4: + Or CL, AL + + Mov AL, 81h + Out DX, AL + Inc DL + Mov AL, CL + Out DX, AL + Jmp DetectCard7 + +DetectCardDMA1: + Mov BX, 5 + Test AL, 20h + JNZ DetectCardDMA2 + + Inc BL + Test AL, 40h + JNZ DetectCardDMA2 + + Inc BL + Test AL, 80h + JNZ DetectCardDMA2 + + Mov BL, 0 + Test AL, 1 + JNZ DetectCardDMA2 + + Inc BL + Test AL, 2 + JNZ DetectCardDMA2 + + Add BL, 2 + Test AL, 8 + JNZ DetectCardDMA2 + +DetectCard8: + Call ResetDSPIRQ + StC + Ret + +DetectCardDMA2: + Cmp DMA, 0FFFFh + JE DetectCardDMA3 + + Cmp BX, DMA + JNE DetectCard8 + +DetectCardDMA3: + Mov DMA, BX + +DetectCard7: + Mov EAX, 'Jeff' + + ClC + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include mmxmsam.inc +include fourier.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc AckIRQ + Assume DS:Driver + + Mov AL, 20h + Cmp CS:IRQ, 7 + JBE AckIRQ1 + + Out 0A0h, AL + +AckIRQ1: + Out 20h, AL + Ret + +EndP AckIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc CheckMIDI + + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Xor BX, BX + Mov DX, MIDIPort + + Mov BL, [MIDIBufferTail] + Test DX, DX + JZ CheckMIDIEnd + + Inc DX + Mov CX, 0FFFFh + +CheckMIDIAgain: + In AL, DX + + Test AL, 80h + LoopNZ CheckMIDIAgain + + Dec DX + In AL, DX + + Cmp AL, 0F0h + JAE CheckMIDIEnd + + Inc BL + Cmp BL, MIDIBufferHead + JE CheckMIDIEnd + + Mov [MIDIBuffer+BX], AL + Mov [MIDIBufferTail], BL +; Jmp CheckMIDIAgain + +CheckMIDIEnd: + Pop DS + Ret + +EndP CheckMIDI + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SB16IRQHandler + + PushAD + Push DS + Push ES + + CLD + +SBIRQAgain: + Mov AX, CS + Mov DS, AX + Assume DS:Driver + + Mov DX, BasePort + Add DL, 4 ; Mixer Port + Mov AL, 82h + Out DX, AL + Inc DL ; DX = BasePort+5 + In AL, DX + + Test AL, 4 + JZ SBMIDIInterruptEnd + + Push AX + Call CheckMIDI + Pop AX + +SBMIDIInterruptEnd: + Test AL, 2 + JNZ SBDigitalInterrupt + + Call AckIRQ + Jmp SBIRQEnd + +SBDigitalInterrupt: + FNSave [FPSave] + + Mov DX, BasePort + Add DL, 0Fh + In AL, DX ; 16-bit IRQ ack. + + Call AckIRQ + +DMAPort1 EQU $+1 + In AL, 1 + Mov BL, AL +DMAPort2 EQU $+1 + In AL, 1 + Mov BH, AL + + Xor AX, AX +DMA16BITADJUST EQU $ + ShL BX, 1 + + Cmp BX, DMABUFFERLENGTH/2 + JB SB16IRQHandler2 + + Mov AX, DMABUFFERLENGTH/2 + +SB16IRQHandler2: + + ; OK... time to get next block + ; Check whether stereo thing is on.. + ; + LES DI, [ActualDMAPtr] + Mov BX, DMASize ; BX = bytes required + Add DI, AX + ShR BX, 1 + ; BX = samples required + Call SaveEMSPageFrame + + Cmp MixTransferRemaining, 0 + JNE SB16IRQHandler4 + Assume DS:Nothing + +SB16IRQHandler3: + Push BX + Push CX + Push BP + Push ES + Push DI + + Call Update + Call MixSamples + Call UpdateFourierBuffer + + Pop DI + Pop ES + Pop BP + Pop CX + Pop BX + +SB16IRQHandler4: + Mov DS, MixSegment + Mov SI, MixTransferOffset + Mov DX, BX ; DX = samples to transfer + Cmp DX, MixTransferRemaining + JBE SB16IRQHandler5 + + Mov DX, MixTransferRemaining + +SB16IRQHandler5: + +include mmxtrans.inc + + Sub MixTransferRemaining, DX ; } Memory write + Sub BX, DX + JNZ SB16IRQHandler3 + + Mov MixTransferOffset, SI ; } Memory write + + Call RestoreEMSPageFrame + + FNRstor [CS:FPSave] + +SBIRQEnd: + Pop ES + Pop DS + PopAD + IRet + +EndP SB16IRQHandler + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + + PushAD + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Add DI, Offset IRQData + Mov BX, [DI] + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset SB16IRQHandler + + XChg [ES:BX], EAX + Mov OldIRQHandler, EAX + + Mov AX, IMR + And AX, [DI+2] + + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Pop ES + Pop DS + PopAD + + Ret + +EndP SetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIRQ + + PushAD + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Mov BX, [IRQData+DI] + + Mov EAX, OldIRQHandler + Mov [ES:BX], EAX + + Pop ES + Pop DS + PopAD + + Ret + +EndP ResetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StartSB16 ; + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + ; Setup DMA + Mov BX, MixSegment + Mov AX, 80 + Mov DX, DMA + Mov DI, DMABUFFERLENGTH + Cmp DX, 3 + JA StartSB16B + + Mov Word Ptr [DMA16BITADJUST], 9090h +StartSB16B: + Call SetDMA + + LES DI, ActualDMAPtr + Xor AX, AX + Mov CX, DMABUFFERLENGTH/2 + Rep StosW + + Mov MixTransferRemaining, 0 + + Mov DX, BasePort + Add DL, 0Ch + + Mov AL, 0D1h ; turn on speaker + Call SBOut + + Mov AL, 40h ; time constant + Call SBOut + Mov AL, SBMixConst + Call SBOut + + Mov AL, 0B6h ; 16 bit, DAC + Call SBOut + Mov AL, Stereo + ShL AL, 5 + Or AL, 10h + Call SBOut + + Mov AX, DMASize + ShR AX, 1 + Dec AX + + Call SBOut ; DMALength, Lo + Mov AL, AH + Call SBOut + + Pop ES + Pop DS + PopA + + Ret + + Assume DS:Nothing + +EndP StartSB16 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixerRegisters + + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Pop DS + + Ret + +EndP GetMixerRegisters + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + Mov SI, Offset RelocationTable + +RelocationFix: + LodsW + Test AX, AX + JZ RelocationEnd + Mov BX, AX + Mov [BX], DS + Jmp RelocationFix + +RelocationEnd: + Call GetEMSPageFrame + Mov EMSPageFrame, AX + + In AL, 0A1h + Mov AH, AL + In AL, 21h + Mov IMR, AX + + Mov DX, BasePort + Add DL, 4 + + Mov AL, 30h + Call SBGetRegister + ShR AL, 3 + Mov VolumeTable, AL + + Mov AL, 31h + Call SBGetRegister + ShR AL, 3 + Mov [VolumeTable+1], AL + + Mov AL, 44h + Call SBGetRegister + ShR AL, 4 + Mov [VolumeTable+2], AL + + Mov AL, 45h + Call SBGetRegister + ShR AL, 4 + Mov [VolumeTable+3], AL + + Mov AL, 46h + Call SBGetRegister + ShR AL, 4 + Mov [VolumeTable+4], AL + + Mov AL, 47h + Call SBGetRegister + ShR AL, 4 + Mov [VolumeTable+5], AL + + Call GetSBMixConst + + ; Parags to allocate = (8/(.4*31*16))*MixSpeed + ; = .04032258*MixSpeed = (65536*.04032258*MixSpeed) / 65536 + + Mov AX, 2643 + Mul MixSpeed + Add AX, 0FFFFh + AdC DX, 5+(DMABUFFERLENGTH*2)/16+(FOURIERBUFFERLENGTH*2)/16 + Mov BX, DX + + ; Allocate MixSegment first + Mov AH, 48h + + Int 21h + JNC InitSound1 + +InitSoundNoMemory: + Mov SI, Offset SB16NoMemoryMsg + Ret + +InitSound1: + Mov MixSegment, AX + Add AX, DX + Sub AX, (FOURIERBUFFERLENGTH*2)/16 + Mov FourierSegment, AX + + Call SetIRQ + Call GetTempo + Call SetTempo + + Mov DX, 330h + Call DetectUART + JC DetectMIDI1 + + Mov MIDIPort, 330h + Jmp DetectMIDIEnd + +DetectMIDI1: + Mov DX, 300h + Call DetectUART + JC DetectMIDIEnd + + Mov MIDIPort, 300h + +DetectMIDIEnd: + Call CalculateFilterCoefficients + + Mov SI, Offset SB16Msg + + Mov AX, BasePort + Mov BX, IRQ + Mov CX, DMA + + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, BasePort + Call ResetDSP + + Call ResetUART + Call ResetIRQ + + ; Delay.. + Mov DX, BasePort + Add DL, 0Ch + + Mov CX, 1000 +ReInitSound1: + In AL, DX + Loop ReInitSound1 + + Call SetIRQ + Call ReinitUART + + Mov SI, Offset ReInitMsg + Mov BX, 40 + Call SetInfoLine + + Mov AL, Stereo + Call SetStereo + + Pop ES + Pop DS + PopA + + Ret + +EndP ReInitSound + Assume DS:Nothing + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Call GotoHomeDirectory + + Mov DS, Word Ptr [CS:DriverName+2] + Mov DX, Word Ptr [CS:DriverName] + + Mov AX, 3D02h ; Read write access + Int 21h + + Push CS + Pop DS + Assume DS:Driver + + JC SaveConfig2 + + Mov BX, AX + + Mov AX, 4200h + Xor CX, CX + Mov DX, Offset CONFIGURATIONOFFSET + Int 21h + JC SaveConfig1 + + Mov AH, 40h + Mov CX, CONFIGSIZE + Mov DX, Offset MixMode + Int 21h + +SaveConfig1: + Mov AH, 3Eh + Int 21h + +SaveConfig2: + Mov DX, CS:BasePort + Add DL, 0Ch + + Mov AL, 0D9h + Call SBOut + + Call ResetUART + + Mov AX, BasePort + Call ResetDSP + + Call ResetDSPDMA + Call ResetDSPIRQ + + Mov AX, IMR + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Mov AX, MixSegment + Test AX, AX + JZ UnInitSound1 + + Mov ES, AX + Mov AH, 49h ; Release MixSegment + Int 21h + + Call ResetIRQ + +UnInitSound1: + Ret + +EndP UnInitSound + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + Push CS + Pop DS + Assume DS:Driver + +Poll1: + Call [UARTBufferEmpty] + JNC PollEnd + + Xor BX, BX + + ClI + + Mov BL, MIDIBufferHead + Cmp BL, MIDIBufferTail + JZ PollEnd ; Nothing in queue + + Inc BL + Mov AL, [MIDIBuffer+BX] + Mov MIDIBufferHead, BL + + Call [UARTSend] + Jmp Poll1 + +PollEnd: + StI + + Ret + +EndP Poll + Assume DS:Nothing + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Push AX + Push BX + Push DX + + Push BX + + Mov AX, MixSpeed + Mov BX, AX + Xor DX, DX + + ShL AX, 1 + RCL DX, 1 ; DX:AX = Mixspeed*2 + + ShR BX, 1 ; BX = Mixspeed/2 + + Add AX, BX + AdC DX, 0 ; DX:AX = Mixspeed*2.5 + + Pop BX ; BX = tempo + Div BX + + Mov BytesToMix, AX + + Pop DX + Pop BX + Pop AX + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + Mov CS:MixVolume, AX + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Jmp CS:RecalculateAllVolumes + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Cmp CS:MixSegment, 0 + JE SetStereo1 + + Mov CS:Stereo, AL + Mov AX, CS:BasePort + Call ResetDSP + + Call StartSB16 + +SetStereo1: + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include loadsam.inc + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset SB16ScreenList + + ClC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far ; Returns AX, given DI + + Xor AH, AH + Mov AL, [CS:VolumeTable+DI] + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +TempVariable DW 0 +Const1 DD 3F800000h + +Proc GetFilterFrequency ; Given AL= Freq + Assume DS:Driver + + ShL AX, 8 + Mov TempVariable, AX + FILD TempVariable + + FMul FreqParameterMultiplier ; -i/(24*256) + FLd ST + FRndInt + FSub ST(1), ST + FXCh + F2XM1 + FLd1 + FAdd + FScale ; = 2^(i/24*256) + FMul FreqMultiplier ; = r + + FLd1 ; 1, c + FAdd ST, ST(1) ; 1+c, c + FDivR Const1 ; 1/(1+c), c + FSt DWord Ptr [SI] + FMul + FStP DWord Ptr [SI+4] + FStP ST + + Ret + +EndP GetFilterFrequency + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Const1On16 DD 3D000000h ; actually 1 on 32 + +Proc CalculateFilterCoefficients + Assume DS:Driver + + PushA + + FNInit + FLdCW NewControlWord + + Mov AL, [VolumeTable+6] + Mov SI, Offset FilterCoefficients + ShR AL, 1 + Call GetFilterFrequency + + Mov AL, [VolumeTable+7] ; FilterFrequency1 + Add SI, 8 + Call GetFilterFrequency + + Mov AL, [VolumeTable+8] ; FilterFrequency1 + Add SI, 8 + Call GetFilterFrequency + + Mov AL, [VolumeTable+9] ; FilterFrequency1 + Add SI, 8 + Call GetFilterFrequency + +; Now volumes + Mov SI, Offset VolumeTable+10 + Mov DI, Offset FilterVolumes + Xor AX, AX + Mov CX, 4 + +FilterVolumeLoop1: + LodSB + Mov TempVariable, AX + FILD TempVariable + FMul Const1On16 + FStP DWord Ptr [DI] + + Add DI, 4 + Loop FilterVolumeLoop1 + + PopA + Ret + +EndP CalculateFilterCoefficients + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far ; Given AX, DI + + Push DS + Push DX + + Push CS + Pop DS + Assume DS:Driver + + Mov [VolumeTable+DI], AL + + Cmp DI, 9 + JA SetVariable3 + + Cmp DI, 6 + JB SetVariable1 + + JE SetVariable2 + + Cmp AL, [VolumeTable+DI-1] + JAE SetVariable2 + + Mov AL, [VolumeTable+DI-1] + Mov [VolumeTable+DI], AL + +SetVariable2: + Cmp DI, 9 + JAE SetVariable3 + + Cmp AL, [VolumeTable+DI+1] + JBE SetVariable3 + + Mov AL, [VolumeTable+DI+1] + Mov [VolumeTable+DI], AL + +SetVariable3: + Call CalculateFilterCoefficients + Jmp SetVariableEnd + +SetVariable1: + Mov DX, BasePort + Add DL, 4 + Mov AL, 30h + Mov AH, [VolumeTable] + ShL AH, 3 + Out DX, AX + + Mov AL, 31h + Mov AH, [VolumeTable+1] + ShL AH, 3 + Out DX, AX + + Mov AL, 44h + Mov AH, [VolumeTable+2] + ShL AH, 4 + Out DX, AX + + Mov AL, 45h + Mov AH, [VolumeTable+3] + ShL AH, 4 + Out DX, AX + + Mov AL, 46h + Mov AH, [VolumeTable+4] + ShL AH, 4 + Out DX, AX + + Mov AL, 47h + Mov AH, [VolumeTable+5] + ShL AH, 4 + Out DX, AX + +SetVariableEnd: + Pop DX + Pop DS + Ret + +EndP SetVariable + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UARTOut + + Push CX + Push DX + Mov DX, CS:MIDIPort + Test DX, DX + JZ UARTOutEnd + + Push AX + Xor CX, CX + Inc DX + +UARTOut1: + In AL, DX + Test AL, 40h + LoopNZ UARTOut1 + + Pop AX + JNZ UARTOutEnd + + Dec DX + Out DX, AL + +UARTOutEnd: + Pop DX + Pop CX + + Ret + +EndP UARTOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +InterpretState DB 0 +InterpretType DB 0 + +Proc SendUARTOut Far ; Local interpreter activated with 0F0h 0F0h. + + Mov AH, CS:InterpretState + Cmp AH, 2 + JB SendUARTOut1 + +; In interpreter. + JE SendUARTOut3 + +; Have InterpretType, now get parameter, then return to normal. + + Cmp AL, 7Fh + JA SendUARTOut4 + + Push BX + + Mov BL, CS:InterpretType ; Want BX = InterpretType*64+Channel + ; + ShL BX, 6 + Add BL, [DI+20h] + And BX, 127 + Mov [CS:FilterParameters+BX], AL + + Pop BX + + Test SI, SI + JZ SendUARTOut4 + + Or Byte Ptr [SI], 64 + +SendUARTOut4: + Mov CS:InterpretState, 0 + Ret + +SendUARTOut3: + Cmp AL, 2 + JAE SendUARTOut4 + + Mov CS:InterpretType, AL + Jmp SendUARTOutStateInc + +SendUARTOut1: + Cmp AL, 0F0h + JNE SendUARTOut2 + +SendUARTOutStateInc: + Inc CS:InterpretState + Ret + +SendUARTOut2: + Test AH, AH + JZ SendUARTOutEnd + + Push AX + Mov AL, 0F0h + Call UARTOut + Pop AX + Mov CS:InterpretState, 0 + +SendUARTOutEnd: + Cmp AL, 0FCh + JE ResetFilters + Cmp AL, 0FAh + JE ResetFilters + + Cmp AL, 0FFh + JNE SendUARTOutNoClear + +ResetFilters: + PushA + Push ES + + Push CS + Pop ES + + Mov DI, Offset FilterParameters + Mov CX, 64 + Mov AL, 7Fh + Rep StosB + Mov CX, 64 + Xor AX, AX + Rep StosB + + Pop ES + PopA + +SendUARTOutNoClear: + Call UARTOut + Ret + +EndP SendUARTOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetWaveForm Far ; Given ES:DI = destination + Assume DS:Nothing ; want 2048 samples. + + PushA + Push DS + + Mov DS, FourierSegment + Mov SI, FourierBufferStart + Mov CX, 2048 + +GetWaveForm1: + MovsW + And SI, (FOURIERBUFFERLENGTH*2)-1 + Loop GetWaveForm1 + + Pop DS + PopA + + Ret + +EndP GetWaveForm + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. + +StopAfterPlay DW 0 +DefaultChannels DW 128 + DW 7 ; MIDI, hiqual + DW 4 Dup (0) + + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + + DW Offset SendUARTOut + + DW Offset GetWaveform + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/SB2DRV.ASM b/SoundDrivers/SB2DRV.ASM new file mode 100755 index 0000000..fdf6f06 --- /dev/null +++ b/SoundDrivers/SB2DRV.ASM @@ -0,0 +1,1421 @@ + + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;********************************** + +STEREOENABLED EQU 0 +DMABUFFERLENGTH EQU 4096 +MIXRESOLUTION EQU 16 ; 16 bit mixing for the SB Pro +MIXTABLESIZE EQU 2*256*65 + +SBProMsg DB "Sound Blaster 2 detected", 13 + DB "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, DMA ", 0FDh, "D", 0 + +SBProNoMemoryMsg DB "Sound Blaster 2 detected", 13 + DB "Error: Insufficient memory", 0 + +ReinitMsg DB "Sound Blaster reinitialised", 0 + +ConfigErrorMsg DB "Error saving configuration to ITSB2.DRV", 0 +ConfigOKMsg DB "Configuration saved to ITSB2.DRV", 0 + +BLASTERString DB "BLASTER" +DriverName DB "ITSB2.DRV", 0 + +BlasterEnvironment Label DWord +BlasterOffset DW 0 +BlasterSegment DW 0 + +DSPVersion DW 0 +Forced DB 0 + +BytesToMix DW 1000 +SBMixConst DB 0 + +MixSegment DW 0 +DMASegment DW 0 + +MixTransferOffset DW 0 +MixTransferRemaining DW 0 + +CONFIGURATIONOFFSET EQU $+128 +CONFIGSIZE EQU 4 +MixModeOffset DW 0 +DMASize DW 1024 + +MixLength DW 0 + +IMR DW 0 +OldIRQHandler DD 0 + +IRQData Label Word + DW 20h, 1111111111111110b ; IRQ 0 + DW 24h, 1111111111111101b ; IRQ 1 + DW 28h, 1111110111111011b ; IRQ 2 + DW 2Ch, 1111111111110111b ; IRQ 3 + DW 30h, 1111111111101111b ; IRQ 4 + DW 34h, 1111111111011111b ; IRQ 5 + DW 38h, 1111111110111111b ; IRQ 6 + DW 3Ch, 1111111101111111b ; IRQ 7 + DW 1C0h, 1111111011111011b ; IRQ 8 + DW 1C4h, 1111110111111011b ; IRQ 9 + DW 1C8h, 1111101111111011b ; IRQ 10 + DW 1CCh, 1111011111111011b ; IRQ 11 + DW 1D0h, 1110111111111011b ; IRQ 12 + DW 1D4h, 1101111111111011b ; IRQ 13 + DW 1D8h, 1011111111111011b ; IRQ 14 + DW 1DCh, 0111111111111011b ; IRQ 15 + + +;********************************** + +SBProScreenList Label + DW 6 + DW Near Ptr IdleFunctionList + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr SB16HeaderLine + DW Near Ptr DriverText + + DW Near Ptr MixModeHeader + DW Near Ptr MixModeButton1 ; 6 + DW Near Ptr MixModeButton2 ; 7 + + DW 0 + +MixModeHeader DW 1 + DB 3, 14 + DB 20h + DB "Mixing Mode, Playback Frequency: ", 0FDh, "DHz", 0 +MixSpeed DW 43478 + +MixModeButton1 DW 2 + DW 0FFFFh, 7, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment1 DW 0 + DW 0 + DW Offset SetMixMode +DriverSegment2 DW 0 + DB 5, 16, 34, 18, 8 + DB 0 + DB " 16 Bit, Non-Interpolated", 0 + +MixModeButton2 DW 2 + DW 6, 0FFFFh, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment3 DW 0 + DW 120 + DW Offset SetMixMode +DriverSegment4 DW 0 + DB 5, 19, 34, 21, 8 + DB 0 + DB " 16 Bit, Interpolated", 0 + +SB16HeaderLine DW 10 + DB "Sound Blaster 2 Driver", 0 + +DriverText DW 1 + DB 32, 48 + DB 21h + DB "Sound Blaster 2 Driver 1.0 for Impulse Tracker", 0 + +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +IdleFunctionList DD 0 + DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +; ÄÄ MixingRoutines ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixBufferPos DW 0 + +include dma.inc +include mix.inc +include mono12b.mix +include mono12bi.mix + +MixFunctionTables Label + +include mono12b.inc ; contains the tables +include mono12bi.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SBOut ; AL = data + ; DX = 2xCh + + Push AX + +SBOut1: + In AL, DX + Test AL, AL + JS SBOut1 + + Pop AX + Out DX, AL + + Ret + +EndP SBOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SBIn ; DX = 2xEh, returns AL + +SBIn1: + In AL, DX + Test AL, AL + JNS SBIn1 + + Add DL, 0Ah-0Eh ; DX = 2xAh -> Data read port + In AL, DX + Add DL, 0Eh-0Ah + + Ret + +EndP SBIn + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixMode Far + + Push CS + Pop ES + Mov DI, Offset MixModeOffset + + Ret + +EndP GetMixMode + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixMode Far + + Mov AX, [SI+22] + + ClI + + Mov CS:MixModeOffset, AX + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS:RecalculateAllVolumes + + StI + + Call GotoHomeDirectory + + ; Now to save config into driver file. + Push CS + Pop DS + Assume DS:Driver + + Mov AX, 3D02h ; Read write access + Mov DX, Offset DriverName + Mov SI, Offset ConfigErrorMsg + Int 21h + JC SetMixMode1 + + Mov BX, AX + + Mov AX, 4200h + Xor CX, CX + Mov DX, Offset CONFIGURATIONOFFSET + Int 21h + JC SetMixMode2 + + Mov AH, 40h + Mov CX, CONFIGSIZE + Mov DX, Offset MixModeOffset + Int 21h + +SetMixMode2: + PushF + Mov AH, 3Eh + Int 21h + PopF + + JC SetMixMode1 + + Mov SI, Offset ConfigOKMsg + +SetMixMode1: + Mov BX, 40 + Call SetInfoLine + + Mov AX, 1 + Ret + +EndP SetMixMode + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SBGetRegister + + Out DX, AL + Inc DX + In AL, DX + Dec DX + + Ret + +EndP SBGetRegister + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetSBMixConst ; Work out value.. and nearest + ; mixspeed value. + + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, CmdLineMixSpeed + Mov CX, MixSpeed + Test AX, AX + JZ GetSBMixConst1 + + Mov CX, 43478 + Cmp AX, CX + JA GetSBMixConst1 + + Mov CX, 12000 + Cmp AX, CX + JB GetSBMixConst1 + + Mov CX, AX + +GetSBMixConst1: + Mov AX, 1000 + Mul AX + Div CX + Mov AH, AL + Neg AH + Mov SBMixConst, AH + + MovZX BX, AL + Mov AX, 1000 + Mul AX + Div BX + Mov MixSpeed, AX + + Pop DS + PopA + Ret + +EndP GetSBMixConst + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetDSP Far ; AX = Port + + Push AX + Push CX + Push DX + + Mov DX, AX + Add DL, 6 + Mov AL, 1 + Out DX, AL + + In AL, DX + In AL, DX + In AL, DX + In AL, DX + + Xor AL, AL + Out DX, AL + + Add DL, 8 + Mov CX, 200 + +ResetDSP1: + In AL, DX + Test AL, AL + JS ResetDSP2 + Loop ResetDSP1 + Jmp ResetDSP3 + +ResetDSP2: + Sub DL, 4 + In AL, DX + Cmp AL, 0AAh + JE ResetDSP4 + Add DL, 4 + Loop ResetDSP1 + +ResetDSP3: + StC + +ResetDSP4: + Pop DX + Pop CX + Pop AX + Ret + +EndP ResetDSP + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far + + Push CS + Pop DS + Assume DS:Driver + + Mov Forced, AL + + Mov AX, BasePort + Cmp AX, 0FFFFh + JE DetectCard1 + + Cmp AX, 210h + JB DetectCard9 + Cmp AX, 280h + JA DetectCard9 + + Call ResetDSP + JNC DetectCard2 + + Ret + +DetectCard1: + Mov AX, 210h + +DetectCard2: + Call ResetDSP + JNC DetectCard3 + Add AL, 10h + Cmp AL, 80h + JBE DetectCard2 + +DetectCard9: + StC + Ret + +DetectCard3: ; OK... DSP found. + ; Get DSP version + Mov BasePort, AX + + Mov DX, AX + Add DL, 0Ch ; 2xCh -> Data ready to send... + +DetectCardOuputLoop1: + In AL, DX + Test AL, AL + JS DetectCardOuputLoop1 + + Mov AL, 0E1h ; Get DSP version command + Out DX, AL + + Add DL, 0Eh-0Ch ; DX = 2xEh -> Data available status + + Call SBIn + Mov AH, AL ; AH = Major version number + Call SBIn ; AL = Minor version number + + Cmp AH, 2 ; SB DSP = 2.00+ + JAE DetectCard5 + +DetectCard4: + StC + Ret + +DetectCard5: + Mov DSPVersion, AX + + ; Need to detect IRQ/DMA... + + Mov SI, Offset BLASTERString + Mov CX, 7 + Call GetEnvironment ; Returns ES:DI, Carry if error + JC DetectCardError + + Mov BlasterOffset, DI + Mov BlasterSegment, ES + + Cmp IRQ, 0FFFFh + JE DetectCardIRQ3 + Cmp Forced, 0 + JNE DetectCardIRQDone + Jmp DetectCardError + +DetectCardIRQ3: + Push DS + Push SI + + LDS SI, BlasterEnvironment + + Xor DX, DX ; DX = env.. + +DetectCardIRQ1: + LodsB + And AL, AL + JZ DetectCardError + Cmp AL, 'i' + JE DetectCardIRQ2 + Cmp AL, 'I' + JE DetectCardIRQ2 + Jmp DetectCardIRQ1 + +DetectCardIRQ2: + LodsB + And AL, AL + JZ DetectCardIRQEnd + Cmp AL, ' ' + JE DetectCardIRQEnd + Sub AL, '0' + JC DetectCardError + Cmp AL, 9 + JA DetectCardError + + IMul DX, 10 + Add DL, AL + Jmp DetectCardIRQ2 + +DetectCardIRQEnd: + Pop SI + Pop DS + + Mov IRQ, DX + +DetectCardIRQDone: + Cmp DMA, 0FFFFh + JE DetectCardDMA3 + Cmp Forced, 0 + JNE DetectCardDMADone + Jmp DetectCardError + +DetectCardDMA3: + Push DS + Push SI + + LDS SI, BlasterEnvironment + + Xor DX, DX ; DX = env.. + +DetectCardDMA1: + LodsB + And AL, AL + JZ DetectCardError + Cmp AL, 'd' + JE DetectCardDMA2 + Cmp AL, 'D' + JE DetectCardDMA2 + Jmp DetectCardDMA1 + +DetectCardDMA2: + LodsB + And AL, AL + JZ DetectCardDMAEnd + Cmp AL, ' ' + JE DetectCardDMAEnd + Sub AL, '0' + JC DetectCardError + Cmp AL, 9 + JA DetectCardError + + IMul DX, 10 + Add DL, AL + Jmp DetectCardDMA2 + +DetectCardDMAEnd: + Pop SI + Pop DS + + Mov DMA, DX + +DetectCardDMADone: + Mov EAX, 'Jeff' + + ClC + Ret + +DetectCardError: + StC + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc MixSamples ; Given DS:SI = info tables, CX = numchannels + + ; 1. Clean buffer + ; + update variables + ; 2. Update parameters + ; 3. Mix func + ; 4. Return + + Push CX + + Mov CX, BytesToMix + Mov ES, MixSegment + Mov DI, MIXTABLESIZE + Mov AX, 2020h + + Mov BX, CX ; BX = bytes to mix + Mov DX, CX + +; Add CX, CX + + Mov MixTransferOffset, DI ; } Memory write + Rep StosW ; } Memory write + Mov MixTransferRemaining, DX ; } + + Pop CX + +MixSamples2: + Test Byte Ptr [SI], 1 + JZ MixSamplesEnd2 + Cmp Byte Ptr [SI+36h], 100 + JE MixSamplesEnd2 + + Push CX + Mov CX, [SI] + + Test CH, 2 + JZ MixSamples3 + And Byte Ptr [SI], Not 1 + Jmp MixSamplesEnd + +MixSamples3: + Test CL, 20h ; New freq? + JZ MixSamples5 + + Mov AX, [SI+10h] + Mov DX, [SI+12h] + Mov BX, MixSpeed + Cmp DX, BX + JAE MixSamplesHandleError + + Div BX + ShL EAX, 16 + Xor AX, AX + Div BX + Mov STEPVALUE, EAX + +MixSamples4: + Test CH, 1 + JZ MixSamples5 + + Mov DWord Ptr [SI+1Ch], 0 ; Current Volume = 0 + ; for volume sliding. +MixSamples5: + Test CX, 8440h ; New volume or panning? + JZ MixSamplesMix + + Xor AX, AX + Test CH, 8 ; Muted? + JNZ MixModeCommon + +Mix0Mode: ; 16-bit mixing, no interpolation, no ramping +Mix0ModeMono: + Mov AL, [SI+20h] + ShR AL, 1 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AX, 30 ; Use left only-mixing for mono + +MixModeCommon: ; Requires AX = 30/60/90 etc. depending + ; On mixing mode type. + ; This will add 180 for 16-bit, + ; And sort out loop types. + Mov BL, [SI+0Ah] + Test Byte Ptr [SI+18h], 2 ; 16 bit? + JZ MixModeCommon1 + + Add AX, 60 + +MixModeCommon1: + Cmp BL, 8 + JB MixModeCommon3 ; No loop + JE MixModeCommon2 ; Forwards loop + + Add AX, 10 + +MixModeCommon2: + Add AX, 10 + +MixModeCommon3: + Add AX, Offset MixFunctionTables + Add AX, MixModeOffset + Mov [SI+8], AX ; Offset... + + +MixSamplesMix: + Mov BX, [SI+8] ; BX = offset into + Mov EAX, [CS:BX+2] + Mov DWord Ptr PreMixFunction, EAX + Mov EAX, [CS:BX+6] + Mov DWord Ptr MixFunctionSeparateBackwards, EAX + + Mov AX, MixTransferRemaining + Mov MixBlockSize, AX + Mov MixBufferOffset, MIXTABLESIZE + + Mov EAX, CURRENTPOSITION + Mov OLDPOSITION, EAX + + Call Word Ptr [CS:BX] + + And Word Ptr [SI], 0111100010001101b + Jmp MixSamplesEnd + +MixSamplesHandleError: + Mov Word Ptr [SI], 200h + + Test Byte Ptr [SI+3Ah], 80h + JNZ MixSamplesEnd + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Turn off channel + +MixSamplesEnd: + Pop CX + +MixSamplesEnd2: + Add SI, 128 + Dec CX + JNZ MixSamples2 + + Ret + +EndP MixSamples + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SBProIRQHandler + + PushAD + Push DS + Push ES + + CLD + + Mov AX, CS + Mov DS, AX + Assume DS:Driver + + Mov DX, BasePort + Add DL, 0Eh + In AL, DX ; 8-bit IRQ ack. + + Mov AL, 20h + Cmp IRQ, 7 + JBE SBProIRQHandler1 + + Out 0A0h, AL + +SBProIRQHandler1: + Out 20h, AL + + Mov AX, MixBufferPos + Mov BX, AX + Mul DMASize + Cmp AX, DMABUFFERLENGTH + JB SBProIRQHandler2 + + Xor AX, AX + Xor BX, BX + +SBProIRQHandler2: + Inc BX + Mov MixBufferPos, BX + + + ; OK... time to get next block + ; Check whether stereo thing is on.. + ; + LES DI, [ActualDMAPtr] + Add DI, AX + + Mov BX, DMASize ; BX = bytes required + + Call SaveEMSPageFrame + + Cmp MixTransferRemaining, 0 + JNE SBProIRQHandler4 + Assume DS:Nothing + +SBProIRQHandler3: + Push BX + Push ES + Push DI + + Call Update + Call MixSamples + + Pop DI + Pop ES + Pop BX + +SBProIRQHandler4: + Mov DS, MixSegment + Mov SI, MixTransferOffset + Mov DX, BX ; DX = samples to transfer + Cmp DX, MixTransferRemaining + JBE SBProIRQHandler5 + + Mov DX, MixTransferRemaining + +SBProIRQHandler5: + Push DX + +SBProIRQHandler6: + Mov AX, [SI] + SAR AX, 6 + + Test AH, AH + JNZ SBProIRQHandlerClip1 + +SBProIRQHandler7: + StosB ; } Memory write + + Add SI, 2 + Dec DX + JNZ SBProIRQHandler6 + + Pop DX + + Sub MixTransferRemaining, DX ; } Memory write + Sub BX, DX + JNZ SBProIRQHandler3 + + Mov MixTransferOffset, SI ; } Memory write + + Call RestoreEMSPageFrame + + Pop ES + Pop DS + PopAD + IRet + +SBProIRQHandlerClip1: + Mov AL, 00h + JS SBProIRQHandler7 + Mov AL, 0FFh + Jmp SBProIRQHandler7 + +EndP SBProIRQHandler + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + + PushAD + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Add DI, Offset IRQData + Mov BX, [DI] + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset SBProIRQHandler + + XChg [ES:BX], EAX + Mov OldIRQHandler, EAX + + Mov AX, IMR + And AX, [DI+2] + + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Pop ES + Pop DS + PopAD + + Ret + +EndP SetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIRQ + + PushAD + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Mov BX, [IRQData+DI] + + Mov EAX, OldIRQHandler + Mov [ES:BX], EAX + + Pop ES + Pop DS + PopAD + + Ret + +EndP ResetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StartSBPro ; + + PushA + Push ES + + ; Setup DMA + Mov BX, DMASegment + Xor AX, AX + Mov DX, DMA + Mov DI, DMABUFFERLENGTH + Call SetDMA + + LES DI, ActualDMAPtr + Xor AX, AX + Mov CX, DMABUFFERLENGTH/2 + Rep StosW + + Mov MixBufferPos, 0 + Mov MixTransferRemaining, 0 + + Mov DX, BasePort + Add DL, 0Ch + + Mov AL, 40h ; time constant + Call SBOut + Mov AL, SBMixConst + Call SBOut + + Mov AL, 0D1h ; turn on speaker + Call SBOut + + Mov AL, 48h ; Set DMA Size.. + Call SBOut + Mov AX, DMASize + Dec AX + Call SBOut + Mov AL, AH + Call SBOut + + Mov AL, 1Ch + Cmp MixSpeed, 21739 + JBE StartSBPro1 + + Mov AL, 90h + +StartSBPro1: + Call SBOut + + Pop ES + PopA + + Ret + + Assume DS:Nothing + +EndP StartSBPro + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixerRegisters + + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Pop DS + + Ret + +EndP GetMixerRegisters + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, DS + Mov DriverSegment1, AX + Mov DriverSegment2, AX + Mov DriverSegment3, AX + Mov DriverSegment4, AX + + Call GetEMSPageFrame + Mov EMSPageFrame, AX + + In AL, 0A1h + Mov AH, AL + In AL, 21h + Mov IMR, AX + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + Call GetSBMixConst + + ; Parags to allocate = (2/(.4*31*16))*MixSpeed + 2080 + ; = 661*MixSpeed/65536 + + Mov AX, 661 + Mul MixSpeed + Add AX, 0FFFFh + AdC DX, 2080 + + Mov BX, (DMABUFFERLENGTH*2)/16 + Add BX, DX + + ; Allocate MixSegment first + Mov AH, 48h + + Int 21h + JNC InitSound1 + +InitSoundNoMemory: + Mov SI, Offset SBProNoMemoryMsg + Ret + +InitSound1: + Mov MixSegment, AX + Add AX, DX + Mov DMASegment, AX + + Call SetIRQ + Call GetTempo + Call SetTempo + Call StartSBPro + + Mov SI, Offset SBProMsg + + Mov AX, BasePort + Mov BX, IRQ + Mov CX, DMA + + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Call ResetIRQ + Call SetIRQ + + Mov SI, Offset ReInitMsg + Mov BX, 40 + Call SetInfoLine + + Mov AX, CS:BasePort + Call ResetDSP + Call StartSBPro + + Pop ES + Pop DS + PopA + + Ret + +EndP ReInitSound + Assume DS:Nothing + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Mov AX, BasePort + Call ResetDSP + + Mov AX, IMR + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Mov AX, MixSegment + Test AX, AX + JZ UnInitSound1 + + Mov ES, AX + Mov AH, 49h ; Release MixSegment + Int 21h + + Call ResetIRQ + +UnInitSound1: + Ret + +EndP UnInitSound + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + Ret + +EndP Poll + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Push AX + Push BX + Push DX + + Push BX + + Mov AX, MixSpeed + Mov BX, AX + Xor DX, DX + + ShL AX, 1 + RCL DX, 1 ; DX:AX = Mixspeed*2 + + ShR BX, 1 ; BX = Mixspeed/2 + + Add AX, BX + AdC DX, 0 ; DX:AX = Mixspeed*2.5 + + Pop BX ; BX = tempo + Div BX + + Mov BytesToMix, AX + + Pop DX + Pop BX + Pop AX + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + PushA + Push DS + + Mov BX, AX ; BX = MixVolume + + Mov AX, CS:MixSegment + Test AX, AX + JZ SetMixVolume2 + + Mov DS, AX + + Mov CX, MIXTABLESIZE/2 + Mov SI, MIXTABLESIZE-2; Starting point - working backwards + +SetMixVolume1: + Mov AX, CX + + Dec AX ; AH = volume, AL = wave value. + Xor DX, DX + XChg AH, DL ; DL = Volume, AX = wave value + CBW + + IMul DX ; DX:AX = Volume * Wave Value + ; Ranges -8192->8128 + + IMul BX ; DX:AX = Volume * Wave Value * Mixing Volume + ; Ranges -1048576->1040384 + + Add AX, 64 + AdC DX, 0 + + ShRD AX, DX, 7 + Mov [SI], AX + Sub SI, 2 + + Loop SetMixVolume1 + +SetMixVolume2: + Pop DS + PopA + + Ret + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include loadsam.inc + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset SBProScreenList + + ClC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far ; Returns AX, given DI + + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far ; Given AX, DI + + Ret + +EndP SetVariable + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. + +StopAfterPlay DW 0 +DefaultChannels DW 64 + DW 5 Dup (0) + + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/SBDRV.ASM b/SoundDrivers/SBDRV.ASM new file mode 100755 index 0000000..3bf7123 --- /dev/null +++ b/SoundDrivers/SBDRV.ASM @@ -0,0 +1,1416 @@ + + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;********************************** + +STEREOENABLED EQU 0 +DMABUFFERLENGTH EQU 1024 +MIXRESOLUTION EQU 16 ; 16 bit mixing for the SB Pro +MIXTABLESIZE EQU 2*256*65 + +SBProMsg DB "Sound Blaster detected", 13 + DB "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, DMA ", 0FDh, "D", 0 + +SBProNoMemoryMsg DB "Sound Blaster detected", 13 + DB "Error: Insufficient memory", 0 + +ReinitMsg DB "Sound Blaster reinitialised", 0 + +ConfigErrorMsg DB "Error saving configuration to ITSB.DRV", 0 +ConfigOKMsg DB "Configuration saved to ITSB.DRV", 0 + +BLASTERString DB "BLASTER" +DriverName DB "ITSB.DRV", 0 + +BlasterEnvironment Label DWord +BlasterOffset DW 0 +BlasterSegment DW 0 + +Forced DB 0 + +BytesToMix DW 1000 +SBMixConst DB 0 + +MixSegment DW 0 +DMASegment DW 0 + +MixTransferOffset DW 0 +MixTransferRemaining DW 0 + +CONFIGURATIONOFFSET EQU $+128 +CONFIGSIZE EQU 4 +MixModeOffset DW 0 +DMASize DW 512 + +MixLength DW 0 + +IMR DW 0 +OldIRQHandler DD 0 + +IRQData Label Word + DW 20h, 1111111111111110b ; IRQ 0 + DW 24h, 1111111111111101b ; IRQ 1 + DW 28h, 1111110111111011b ; IRQ 2 + DW 2Ch, 1111111111110111b ; IRQ 3 + DW 30h, 1111111111101111b ; IRQ 4 + DW 34h, 1111111111011111b ; IRQ 5 + DW 38h, 1111111110111111b ; IRQ 6 + DW 3Ch, 1111111101111111b ; IRQ 7 + DW 1C0h, 1111111011111011b ; IRQ 8 + DW 1C4h, 1111110111111011b ; IRQ 9 + DW 1C8h, 1111101111111011b ; IRQ 10 + DW 1CCh, 1111011111111011b ; IRQ 11 + DW 1D0h, 1110111111111011b ; IRQ 12 + DW 1D4h, 1101111111111011b ; IRQ 13 + DW 1D8h, 1011111111111011b ; IRQ 14 + DW 1DCh, 0111111111111011b ; IRQ 15 + + +;********************************** + +SBProScreenList Label + DW 6 + DW Near Ptr IdleFunctionList + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr SB16HeaderLine + DW Near Ptr DriverText + + DW Near Ptr MixModeHeader + DW Near Ptr MixModeButton1 ; 6 + DW Near Ptr MixModeButton2 ; 7 + + DW 0 + +MixModeHeader DW 1 + DB 3, 14 + DB 20h + DB "Mixing Mode, Playback Frequency: ", 0FDh, "DHz", 0 +MixSpeed DW 21739 + +MixModeButton1 DW 2 + DW 0FFFFh, 7, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment1 DW 0 + DW 0 + DW Offset SetMixMode +DriverSegment2 DW 0 + DB 5, 16, 34, 18, 8 + DB 0 + DB " 16 Bit, Non-Interpolated", 0 + +MixModeButton2 DW 2 + DW 6, 0FFFFh, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment3 DW 0 + DW 120 + DW Offset SetMixMode +DriverSegment4 DW 0 + DB 5, 19, 34, 21, 8 + DB 0 + DB " 16 Bit, Interpolated", 0 + +SB16HeaderLine DW 10 + DB "Sound Blaster Driver", 0 + +DriverText DW 1 + DB 34, 48 + DB 21h + DB "Sound Blaster Driver 1.0 for Impulse Tracker", 0 + +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +IdleFunctionList DD 0 + DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +; ÄÄ MixingRoutines ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixBufferPos DW 0 + +include dma.inc +include mix.inc +include mono12b.mix +include mono12bi.mix + +MixFunctionTables Label + +include mono12b.inc ; contains the tables +include mono12bi.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SBOut ; AL = data + ; DX = 2xCh + + Push AX + +SBOut1: + In AL, DX + Test AL, AL + JS SBOut1 + + Pop AX + Out DX, AL + + Ret + +EndP SBOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SBIn ; DX = 2xEh, returns AL + +SBIn1: + In AL, DX + Test AL, AL + JNS SBIn1 + + Add DL, 0Ah-0Eh ; DX = 2xAh -> Data read port + In AL, DX + Add DL, 0Eh-0Ah + + Ret + +EndP SBIn + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixMode Far + + Push CS + Pop ES + Mov DI, Offset MixModeOffset + + Ret + +EndP GetMixMode + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixMode Far + + Mov AX, [SI+22] + + ClI + + Mov CS:MixModeOffset, AX + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS:RecalculateAllVolumes + + StI + + Call GotoHomeDirectory + + ; Now to save config into driver file. + Push CS + Pop DS + Assume DS:Driver + + Mov AX, 3D02h ; Read write access + Mov DX, Offset DriverName + Mov SI, Offset ConfigErrorMsg + Int 21h + JC SetMixMode1 + + Mov BX, AX + + Mov AX, 4200h + Xor CX, CX + Mov DX, Offset CONFIGURATIONOFFSET + Int 21h + JC SetMixMode2 + + Mov AH, 40h + Mov CX, CONFIGSIZE + Mov DX, Offset MixModeOffset + Int 21h + +SetMixMode2: + PushF + Mov AH, 3Eh + Int 21h + PopF + + JC SetMixMode1 + + Mov SI, Offset ConfigOKMsg + +SetMixMode1: + Mov BX, 40 + Call SetInfoLine + + Mov AX, 1 + Ret + +EndP SetMixMode + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SBGetRegister + + Out DX, AL + Inc DX + In AL, DX + Dec DX + + Ret + +EndP SBGetRegister + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetSBMixConst ; Work out value.. and nearest + ; mixspeed value. + + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, CmdLineMixSpeed + Mov CX, MixSpeed + Test AX, AX + JZ GetSBMixConst1 + + Mov CX, 21739 + Cmp AX, CX + JA GetSBMixConst1 + + Mov CX, 12000 + Cmp AX, CX + JB GetSBMixConst1 + + Mov CX, AX + +GetSBMixConst1: + Mov AX, 1000 + Mul AX + Div CX + Mov AH, AL + Neg AH + Mov SBMixConst, AH + + MovZX BX, AL + Mov AX, 1000 + Mul AX + Div BX + Mov MixSpeed, AX + + Pop DS + PopA + Ret + +EndP GetSBMixConst + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetDSP Far ; AX = Port + + Push AX + Push CX + Push DX + + Mov DX, AX + Add DL, 6 + Mov AL, 1 + Out DX, AL + + In AL, DX + In AL, DX + In AL, DX + In AL, DX + + Xor AL, AL + Out DX, AL + + Add DL, 8 + Mov CX, 200 + +ResetDSP1: + In AL, DX + Test AL, AL + JS ResetDSP2 + Loop ResetDSP1 + Jmp ResetDSP3 + +ResetDSP2: + Sub DL, 4 + In AL, DX + Cmp AL, 0AAh + JE ResetDSP4 + Add DL, 4 + Loop ResetDSP1 + +ResetDSP3: + StC + +ResetDSP4: + Pop DX + Pop CX + Pop AX + Ret + +EndP ResetDSP + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far + + Push CS + Pop DS + Assume DS:Driver + + Mov Forced, AL + + Mov AX, BasePort + Cmp AX, 0FFFFh + JE DetectCard1 + + Cmp AX, 210h + JB DetectCard9 + Cmp AX, 290h + JA DetectCard9 + + Call ResetDSP + JNC DetectCard2 + + Ret + +DetectCard1: + Mov AX, 210h + +DetectCard2: + Call ResetDSP + JNC DetectCard3 + Add AL, 10h + Cmp AL, 80h + JBE DetectCard2 + +DetectCard9: + StC + Ret + +DetectCard3: ; OK... DSP found. + ; Get DSP version + Mov BasePort, AX + + Mov DX, AX + Add DL, 0Ch ; 2xCh -> Data ready to send... + +DetectCardOuputLoop1: + In AL, DX + Test AL, AL + JS DetectCardOuputLoop1 + + Mov SI, Offset BLASTERString + Mov CX, 7 + Call GetEnvironment ; Returns ES:DI, Carry if error + JC DetectCardDefault + + Mov BlasterOffset, DI + Mov BlasterSegment, ES + + Cmp IRQ, 0FFFFh + JE DetectCardIRQ3 + Cmp Forced, 0 + JNE DetectCardIRQDone + Jmp DetectCardError + +DetectCardIRQ3: + Push DS + Push SI + + LDS SI, BlasterEnvironment + + Xor DX, DX ; DX = env.. + +DetectCardIRQ1: + LodsB + And AL, AL + JZ DetectCardError + Cmp AL, 'i' + JE DetectCardIRQ2 + Cmp AL, 'I' + JE DetectCardIRQ2 + Jmp DetectCardIRQ1 + +DetectCardIRQ2: + LodsB + And AL, AL + JZ DetectCardIRQEnd + Cmp AL, ' ' + JE DetectCardIRQEnd + Sub AL, '0' + JC DetectCardError + Cmp AL, 9 + JA DetectCardError + + IMul DX, 10 + Add DL, AL + Jmp DetectCardIRQ2 + +DetectCardIRQEnd: + Pop SI + Pop DS + + Mov IRQ, DX + +DetectCardIRQDone: + Cmp DMA, 0FFFFh + JE DetectCardDMA3 + Cmp Forced, 0 + JNE DetectCardDMADone + Jmp DetectCardError + +DetectCardDMA3: + Push DS + Push SI + + LDS SI, BlasterEnvironment + + Xor DX, DX ; DX = env.. + +DetectCardDMA1: + LodsB + And AL, AL + JZ DetectCardError + Cmp AL, 'd' + JE DetectCardDMA2 + Cmp AL, 'D' + JE DetectCardDMA2 + Jmp DetectCardDMA1 + +DetectCardDMA2: + LodsB + And AL, AL + JZ DetectCardDMAEnd + Cmp AL, ' ' + JE DetectCardDMAEnd + Sub AL, '0' + JC DetectCardError + Cmp AL, 9 + JA DetectCardError + + IMul DX, 10 + Add DL, AL + Jmp DetectCardDMA2 + +DetectCardDMAEnd: + Pop SI + Pop DS + + Mov DMA, DX + +DetectCardDMADone: + Mov EAX, 'Jeff' + + ClC + Ret + +DetectCardDefault: + Cmp IRQ, 0FFFFh + JNE DetectCardDefaultDMA + Mov IRQ, 7 + +DetectCardDefaultDMA: + Cmp DMA, 0FFFFh + JNE DetectCardDefaultEnd + Mov DMA, 1 + +DetectCardDefaultEnd: + Mov EAX, 'Jeff' + + ClC + Ret + +DetectCardError: + StC + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc MixSamples ; Given DS:SI = info tables, CX = numchannels + + ; 1. Clean buffer + ; + update variables + ; 2. Update parameters + ; 3. Mix func + ; 4. Return + + Push CX + + Mov CX, BytesToMix + Mov ES, MixSegment + Mov DI, MIXTABLESIZE + Mov AX, 2020h + + Mov BX, CX ; BX = bytes to mix + Mov DX, CX + +; Add CX, CX + + Mov MixTransferOffset, DI ; } Memory write + Rep StosW ; } Memory write + Mov MixTransferRemaining, DX ; } + + Pop CX + +MixSamples2: + Test Byte Ptr [SI], 1 + JZ MixSamplesEnd2 + Cmp Byte Ptr [SI+36h], 100 + JE MixSamplesEnd2 + + Push CX + Mov CX, [SI] + + Test CH, 2 + JZ MixSamples3 + And Byte Ptr [SI], Not 1 + Jmp MixSamplesEnd + +MixSamples3: + Test CL, 20h ; New freq? + JZ MixSamples5 + + Mov AX, [SI+10h] + Mov DX, [SI+12h] + Mov BX, MixSpeed + Cmp DX, BX + JAE MixSamplesHandleError + + Div BX + ShL EAX, 16 + Xor AX, AX + Div BX + Mov STEPVALUE, EAX + +MixSamples4: + Test CH, 1 + JZ MixSamples5 + + Mov DWord Ptr [SI+1Ch], 0 ; Current Volume = 0 + ; for volume sliding. +MixSamples5: + Test CX, 8440h ; New volume or panning? + JZ MixSamplesMix + + Xor AX, AX + Test CH, 8 ; Muted? + JNZ MixModeCommon + +Mix0Mode: ; 16-bit mixing, no interpolation, no ramping +Mix0ModeMono: + Mov AL, [SI+20h] + ShR AL, 1 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AX, 30 ; Use left only-mixing for mono + +MixModeCommon: ; Requires AX = 30/60/90 etc. depending + ; On mixing mode type. + ; This will add 180 for 16-bit, + ; And sort out loop types. + Mov BL, [SI+0Ah] + Test Byte Ptr [SI+18h], 2 ; 16 bit? + JZ MixModeCommon1 + + Add AX, 60 + +MixModeCommon1: + Cmp BL, 8 + JB MixModeCommon3 ; No loop + JE MixModeCommon2 ; Forwards loop + + Add AX, 10 + +MixModeCommon2: + Add AX, 10 + +MixModeCommon3: + Add AX, Offset MixFunctionTables + Add AX, MixModeOffset + Mov [SI+8], AX ; Offset... + + +MixSamplesMix: + Mov BX, [SI+8] ; BX = offset into + Mov EAX, [CS:BX+2] + Mov DWord Ptr PreMixFunction, EAX + Mov EAX, [CS:BX+6] + Mov DWord Ptr MixFunctionSeparateBackwards, EAX + + Mov AX, MixTransferRemaining + Mov MixBlockSize, AX + Mov MixBufferOffset, MIXTABLESIZE + + Mov EAX, CURRENTPOSITION + Mov OLDPOSITION, EAX + + Call Word Ptr [CS:BX] + + And Word Ptr [SI], 0111100010001101b + Jmp MixSamplesEnd + +MixSamplesHandleError: + Mov Word Ptr [SI], 200h + + Test Byte Ptr [SI+3Ah], 80h + JNZ MixSamplesEnd + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Turn off channel + +MixSamplesEnd: + Pop CX + +MixSamplesEnd2: + Add SI, 128 + Dec CX + JNZ MixSamples2 + + Ret + +EndP MixSamples + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SBProIRQHandler + + PushAD + Push DS + Push ES + + CLD + + Mov AX, CS + Mov DS, AX + Assume DS:Driver + + Mov DX, BasePort + Add DL, 0Eh + In AL, DX ; 8-bit IRQ ack. + + Add DL, 0Ch-0Eh + + Mov AL, 14h ; Start output + Call SBOut + Mov AX, DMASize + Dec AX + Call SBOut + Mov AL, AH + Call SBOut + + Mov AL, 20h + Cmp IRQ, 7 + JBE SBProIRQHandler1 + + Out 0A0h, AL + +SBProIRQHandler1: + Out 20h, AL + + Mov AX, MixBufferPos + Mov BX, AX + Mul DMASize + Cmp AX, DMABUFFERLENGTH + JB SBProIRQHandler2 + + Xor AX, AX + Xor BX, BX + +SBProIRQHandler2: + Inc BX + Mov MixBufferPos, BX + + + ; OK... time to get next block + ; Check whether stereo thing is on.. + ; + LES DI, [ActualDMAPtr] + Add DI, AX + + Mov BX, DMASize ; BX = bytes required + + Call SaveEMSPageFrame + + Cmp MixTransferRemaining, 0 + JNE SBProIRQHandler4 + Assume DS:Nothing + +SBProIRQHandler3: + Push BX + Push ES + Push DI + + Call Update + Call MixSamples + + Pop DI + Pop ES + Pop BX + +SBProIRQHandler4: + Mov DS, MixSegment + Mov SI, MixTransferOffset + Mov DX, BX ; DX = samples to transfer + Cmp DX, MixTransferRemaining + JBE SBProIRQHandler5 + + Mov DX, MixTransferRemaining + +SBProIRQHandler5: + Push DX + +SBProIRQHandler6: + Mov AX, [SI] + SAR AX, 6 + + Test AH, AH + JNZ SBProIRQHandlerClip1 + +SBProIRQHandler7: + StosB ; } Memory write + + Add SI, 2 + Dec DX + JNZ SBProIRQHandler6 + + Pop DX + + Sub MixTransferRemaining, DX ; } Memory write + Sub BX, DX + JNZ SBProIRQHandler3 + + Mov MixTransferOffset, SI ; } Memory write + + Call RestoreEMSPageFrame + + Pop ES + Pop DS + PopAD + IRet + +SBProIRQHandlerClip1: + Mov AL, 00h + JS SBProIRQHandler7 + Mov AL, 0FFh + Jmp SBProIRQHandler7 + +EndP SBProIRQHandler + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + + PushAD + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Add DI, Offset IRQData + Mov BX, [DI] + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset SBProIRQHandler + + XChg [ES:BX], EAX + Mov OldIRQHandler, EAX + + Mov AX, IMR + And AX, [DI+2] + + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Pop ES + Pop DS + PopAD + + Ret + +EndP SetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIRQ + + PushAD + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Mov BX, [IRQData+DI] + + Mov EAX, OldIRQHandler + Mov [ES:BX], EAX + + Pop ES + Pop DS + PopAD + + Ret + +EndP ResetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StartSBPro ; + + PushA + Push ES + + ; Setup DMA + Mov BX, DMASegment + Xor AX, AX + Mov DX, DMA + Mov DI, DMABUFFERLENGTH + Call SetDMA + + LES DI, ActualDMAPtr + Xor AX, AX + Mov CX, DMABUFFERLENGTH/2 + Rep StosW + + Mov MixBufferPos, 0 + Mov MixTransferRemaining, 0 + + Mov DX, BasePort + Add DL, 0Ch + + Mov AL, 40h ; time constant + Call SBOut + Mov AL, SBMixConst + Call SBOut + + Mov AL, 0D1h ; turn on speaker + Call SBOut + + Mov AL, 14h ; Start output + Call SBOut + Mov AX, DMASize + Dec AX + Call SBOut + Mov AL, AH + Call SBOut + + Pop ES + PopA + + Ret + + Assume DS:Nothing + +EndP StartSBPro + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixerRegisters + + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Pop DS + + Ret + +EndP GetMixerRegisters + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, DS + Mov DriverSegment1, AX + Mov DriverSegment2, AX + Mov DriverSegment3, AX + Mov DriverSegment4, AX + + Call GetEMSPageFrame + Mov EMSPageFrame, AX + + In AL, 0A1h + Mov AH, AL + In AL, 21h + Mov IMR, AX + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + Call GetSBMixConst + + ; Parags to allocate = (2/(.4*31*16))*MixSpeed + 2080 + ; = 661*MixSpeed/65536 + + Mov AX, 661 + Mul MixSpeed + Add AX, 0FFFFh + AdC DX, 2080 + + Mov BX, (DMABUFFERLENGTH*2)/16 + Add BX, DX + + ; Allocate MixSegment first + Mov AH, 48h + + Int 21h + JNC InitSound1 + +InitSoundNoMemory: + Mov SI, Offset SBProNoMemoryMsg + Ret + +InitSound1: + Mov MixSegment, AX + Add AX, DX + Mov DMASegment, AX + + Call SetIRQ + Call GetTempo + Call SetTempo + Call StartSBPro + + Mov SI, Offset SBProMsg + + Mov AX, BasePort + Mov BX, IRQ + Mov CX, DMA + + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Call ResetIRQ + Call SetIRQ + + Mov SI, Offset ReInitMsg + Mov BX, 40 + Call SetInfoLine + + Mov AX, CS:BasePort + Call ResetDSP + Call StartSBPro + + Pop ES + Pop DS + PopA + + Ret + +EndP ReInitSound + Assume DS:Nothing + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Mov AX, BasePort + Call ResetDSP + + Mov AX, IMR + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Mov AX, MixSegment + Test AX, AX + JZ UnInitSound1 + + Mov ES, AX + Mov AH, 49h ; Release MixSegment + Int 21h + + Call ResetIRQ + +UnInitSound1: + Ret + +EndP UnInitSound + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + Ret + +EndP Poll + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Push AX + Push BX + Push DX + + Push BX + + Mov AX, MixSpeed + Mov BX, AX + Xor DX, DX + + ShL AX, 1 + RCL DX, 1 ; DX:AX = Mixspeed*2 + + ShR BX, 1 ; BX = Mixspeed/2 + + Add AX, BX + AdC DX, 0 ; DX:AX = Mixspeed*2.5 + + Pop BX ; BX = tempo + Div BX + + Mov BytesToMix, AX + + Pop DX + Pop BX + Pop AX + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + PushA + Push DS + + Mov BX, AX ; BX = MixVolume + + Mov AX, CS:MixSegment + Test AX, AX + JZ SetMixVolume2 + + Mov DS, AX + + Mov CX, MIXTABLESIZE/2 + Mov SI, MIXTABLESIZE-2; Starting point - working backwards + +SetMixVolume1: + Mov AX, CX + + Dec AX ; AH = volume, AL = wave value. + Xor DX, DX + XChg AH, DL ; DL = Volume, AX = wave value + CBW + + IMul DX ; DX:AX = Volume * Wave Value + ; Ranges -8192->8128 + + IMul BX ; DX:AX = Volume * Wave Value * Mixing Volume + ; Ranges -1048576->1040384 + + Add AX, 64 + AdC DX, 0 + + ShRD AX, DX, 7 + Mov [SI], AX + Sub SI, 2 + + Loop SetMixVolume1 + +SetMixVolume2: + Pop DS + PopA + + Ret + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include loadsam.inc + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset SBProScreenList + + ClC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far ; Returns AX, given DI + + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far ; Given AX, DI + + Ret + +EndP SetVariable + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. + +StopAfterPlay DW 0 +DefaultChannels DW 64 + DW 5 Dup (0) + + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/SBMIDI.INC b/SoundDrivers/SBMIDI.INC new file mode 100755 index 0000000..0b1f523 --- /dev/null +++ b/SoundDrivers/SBMIDI.INC @@ -0,0 +1,133 @@ + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ Variables ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + +MIDIPort DW 300h + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ Functions ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + +Proc Poll Far + + Mov DX, [CS:MIDIPort] + Test DX, DX + JZ PollEnd + + Call [CS:UARTBufferEmpty] + JNC PollEnd + + Inc DX + In AL, DX + Test AL, 80h + JNZ PollEnd + + Dec DX + In AL, DX + Cmp AL, 0F8h + JAE PollEnd + + Call [CS:UARTSend] + +PollEnd: + Ret + +EndP Poll + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc MIDI_UnInit + + Ret + + Mov DX, MIDIPort + Test DX, DX + JZ UnInitUARTEnd + + Inc DX + + Mov AL, 0FFh + Out DX, AL + +UnInitUARTEnd: + Ret + +EndP MIDI_UnInit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitUART + ; returns carry set if no UART + + Mov BX, 32 ; Number of attempts to read correct + ; value back from the UART + + Inc DX + Mov AL, 0FFh + Out DX, AL ; Reset UART + + Mov AL, 03Fh + Out DX, AL ; UART Mode + + Mov CX, 0FFFFh + +InitUART1: + In AL, DX + Test AL, 80h + LoopNZ InitUART1 + +InitUART2: + StC + JNZ InitUART3 + + Dec DX + In AL, DX + Cmp AL, 0FEh + JE InitUART3 + + Inc DX + Dec BX + JNZ InitUART1 + + StC + +InitUART3: + Ret + +EndP InitUART + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc MIDI_Init + + Mov DX, 301h + Mov AL, 0FFh + Out DX, AL + + Mov AL, 3Fh + Out DX, AL + Ret + + Mov DX, 330h + Call InitUART + + JC MIDI_Init1 + + Mov [CS:MIDIPort], 330h + Jmp MIDI_InitEnd + +MIDI_Init1: + Mov DX, 300h + Call InitUART + JC MIDI_InitEnd + + Mov [CS:MIDIPort], 300h + +MIDI_InitEnd: + Ret + +EndP MIDI_Init + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ diff --git a/SoundDrivers/SBPRODRV.ASM b/SoundDrivers/SBPRODRV.ASM new file mode 100755 index 0000000..b4119b8 --- /dev/null +++ b/SoundDrivers/SBPRODRV.ASM @@ -0,0 +1,2009 @@ + + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;********************************** + +STEREOENABLED EQU 1 +DMABUFFERLENGTH EQU 4096 +MIXRESOLUTION EQU 16 ; 16 bit mixing for the SB Pro +MIXTABLESIZE EQU 2*256*65 + +SBProMsg DB "Sound Blaster Pro detected", 13 + DB "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, DMA ", 0FDh, "D", 0 + +SBProNoMemoryMsg DB "Sound Blaster Pro detected", 13 + DB "Error: Insufficient memory", 0 + +ReinitMsg DB "Sound Blaster Pro reinitialised", 0 + +ConfigErrorMsg DB "Error saving configuration to ITSBPRO.DRV", 0 +ConfigOKMsg DB "Configuration saved to ITSBPRO.DRV", 0 + +BLASTERString DB "BLASTER" +DriverName DB "ITSBPRO.DRV", 0 + +BlasterEnvironment Label DWord +BlasterOffset DW 0 +BlasterSegment DW 0 + +MixSpeed DW 43478 + +DSPVersion DW 0 +Forced DB 0 +Stereo DB 0 + +BytesToMix DW 1000 +SBMixConst DB 0 + +MixSegment DW 0 +DMASegment DW 0 + +MixTransferOffset DW 0 +MixTransferRemaining DW 0 + +CONFIGURATIONOFFSET EQU $+128 +CONFIGSIZE EQU 6 +MixMode DW 0 +MixModeOffset DW 0 +Filter DW 0 +DMASize DW 1024 + +MixLength DW 0 + +IMR DW 0 +OldIRQHandler DD 0 + +IRQData Label Word + DW 20h, 1111111111111110b ; IRQ 0 + DW 24h, 1111111111111101b ; IRQ 1 + DW 28h, 1111110111111011b ; IRQ 2 + DW 2Ch, 1111111111110111b ; IRQ 3 + DW 30h, 1111111111101111b ; IRQ 4 + DW 34h, 1111111111011111b ; IRQ 5 + DW 38h, 1111111110111111b ; IRQ 6 + DW 3Ch, 1111111101111111b ; IRQ 7 + DW 1C0h, 1111111011111011b ; IRQ 8 + DW 1C4h, 1111110111111011b ; IRQ 9 + DW 1C8h, 1111101111111011b ; IRQ 10 + DW 1CCh, 1111011111111011b ; IRQ 11 + DW 1D0h, 1110111111111011b ; IRQ 12 + DW 1D4h, 1101111111111011b ; IRQ 13 + DW 1D8h, 1011111111111011b ; IRQ 14 + DW 1DCh, 0111111111111011b ; IRQ 15 + + +;********************************** + +SBProScreenList Label + DW 6 + DW Near Ptr IdleFunctionList + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr SBProHeaderLine + + DW Near Ptr VolumeText + DW Near Ptr VolumeBox1 + + DW Near Ptr MasterVolumeLeft ; 6 + DW Near Ptr MasterVolumeRight ; 7 + + DW Near Ptr MixModeText + DW Near Ptr MixModeButton1 + DW Near Ptr MixModeButton2 + + DW 0 + +SBProHeaderLine DW 10 + DB "Sound Blaster Pro Driver", 0 + +DriverText DW 1 + DB 30, 48 + DB 21h + DB "Sound Blaster Pro Driver 1.0 for Impulse Tracker", 0 + +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +IdleFunctionList DD 0 + DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +VolumeText DW 1 + DB 2, 14 + DB 20h + DB "Master Volume Left", 13 + DB "Master Volume Right" + DB 0 + +VolumeBox1 DW 0 + DB 21, 13, 27, 16 + DB 25 + +MasterVolumeLeft DW 9 + DB 22, 14 + DW 0, 31 + DW 9, 0 + DW 0FFFFh, 7, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +MasterVolumeRight DW 9 + DB 22, 15 + DW 0, 31 + DW 9, 1 + DW 6, 9, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +MixModeText DW 1 + DB 2, 18 + DB 20h + DB "Mixing Mode, Playback Frequency: ", 0FDh, "DHz", 0 +Frequency DW 0 + +MixModeButton1 DW 2 + DW 7, 10, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment1 DW 0 + DW 0 + DW Offset SetMixMode +DriverSegment2 DW 0 + DB 5, 19, 34, 21, 8 + DB 0 + DB " 16 Bit, Non-Interpolated", 0 + +MixModeButton2 DW 2 + DW 9, 0FFFFh, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment3 DW 0 + DW 2 + DW Offset SetMixMode +DriverSegment4 DW 0 + DB 5, 22, 34, 24, 8 + DB 0 + DB " 16 Bit, Interpolated", 0 + +VolumeTable DB 6 Dup (0) + +; ÄÄ MixingRoutines ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixBufferPos DW 0 +include dma.inc +include mix.inc +include m12bit.mix +include m12biti.mix + +MixFunctionTables Label + +include m12bit.inc ; contains the tables +include m12biti.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc RecalculateAllFrequencies + + Call GetChannelTables + +RecalculateAllFrequencies1: + Or Byte Ptr [SI], 32 + + Add SI, 128 + Dec CX + JNZ RecalculateAllFrequencies1 + + Ret + +EndP RecalculateAllFrequencies + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SBOut ; AL = data + ; DX = 2xCh + + Push AX + +SBOut1: + In AL, DX + Test AL, AL + JS SBOut1 + + Pop AX + Out DX, AL + + Ret + +EndP SBOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SBIn ; DX = 2xEh, returns AL + +SBIn1: + In AL, DX + Test AL, AL + JNS SBIn1 + + Add DL, 0Ah-0Eh ; DX = 2xAh -> Data read port + In AL, DX + Add DL, 0Eh-0Ah + + Ret + +EndP SBIn + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixMode Far + + Push CS + Pop ES + Mov DI, Offset MixMode + + Ret + +EndP GetMixMode + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixMode Far + + Mov AX, [SI+22] + + ClI + + Mov CS:MixMode, AX + + Mov BX, 180 + Mul BX + Mov CS:MixModeOffset, AX + + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS:RecalculateAllVolumes + + StI + + Call GotoHomeDirectory + + ; Now to save config into driver file. + Push CS + Pop DS + Assume DS:Driver + + Mov AX, 3D02h ; Read write access + Mov DX, Offset DriverName + Mov SI, Offset ConfigErrorMsg + Int 21h + JC SetMixMode1 + + Mov BX, AX + + Mov AX, 4200h + Xor CX, CX + Mov DX, Offset CONFIGURATIONOFFSET + Int 21h + JC SetMixMode2 + + Mov AH, 40h + Mov CX, CONFIGSIZE + Mov DX, Offset MixMode + Int 21h + +SetMixMode2: + PushF + Mov AH, 3Eh + Int 21h + PopF + + JC SetMixMode1 + + Mov SI, Offset ConfigOKMsg + +SetMixMode1: + Mov BX, 40 + Call SetInfoLine + + Mov AX, 1 + Ret + +EndP SetMixMode + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SBGetRegister + + Out DX, AL + Inc DX + In AL, DX + Dec DX + + Ret + +EndP SBGetRegister + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetSBMixConst ; Work out value.. and nearest + ; mixspeed value. + + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, CmdLineMixSpeed + Mov CX, MixSpeed + Test AX, AX + JZ GetSBMixConst1 + + Mov CX, 43478 + Cmp AX, CX + JA GetSBMixConst1 + + Mov CX, 12000 + Cmp AX, CX + JB GetSBMixConst1 + + Mov CX, AX + +GetSBMixConst1: + Mov AX, 1000 + Mul AX + Div CX + Mov AH, AL + Neg AH + Mov SBMixConst, AH + + MovZX BX, AL + Mov AX, 1000 + Mul AX + Div BX + Mov MixSpeed, AX + + Pop DS + PopA + Ret + +EndP GetSBMixConst + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetDSP Far ; AX = Port + + Push AX + Push CX + Push DX + + Mov DX, AX + Add DL, 6 + Mov AL, 1 + Out DX, AL + + In AL, DX + In AL, DX + In AL, DX + In AL, DX + + Xor AL, AL + Out DX, AL + + Add DL, 8 + Mov CX, 200 + +ResetDSP1: + In AL, DX + Test AL, AL + JS ResetDSP2 + Loop ResetDSP1 + Jmp ResetDSP3 + +ResetDSP2: + Sub DL, 4 + In AL, DX + Cmp AL, 0AAh + JE ResetDSP4 + Add DL, 4 + Loop ResetDSP1 + +ResetDSP3: + StC + +ResetDSP4: + Pop DX + Pop CX + Pop AX + Ret + +EndP ResetDSP + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far + + Push CS + Pop DS + Assume DS:Driver + + Mov Forced, AL + + Mov AX, BasePort + Cmp AX, 0FFFFh + JE DetectCard1 + + Cmp AX, 210h + JB DetectCard9 + Cmp AX, 280h + JA DetectCard9 + + Call ResetDSP + JNC DetectCard3 + + Ret + +DetectCard1: + Mov AX, 210h + +DetectCard2: + Call ResetDSP + JNC DetectCard3 + Add AL, 10h + Cmp AL, 80h + JBE DetectCard2 + +DetectCard9: + StC + Ret + +DetectCard3: ; OK... DSP found. + ; Get DSP version + Mov BasePort, AX + + Mov DX, AX + Add DL, 0Ch ; 2xCh -> Data ready to send... + +DetectCardOuputLoop1: + In AL, DX + Test AL, AL + JS DetectCardOuputLoop1 + + Mov AL, 0E1h ; Get DSP version command + Out DX, AL + + Add DL, 0Eh-0Ch ; DX = 2xEh -> Data available status + + Call SBIn + Mov AH, AL ; AH = Major version number + Call SBIn ; AL = Minor version number + + Cmp Forced, 0 + JNE DetectCard5 + Cmp AH, 3 ; SB DSP = 3.00+ + JAE DetectCard5 + +DetectCard4: + StC + Ret + +DetectCard5: + Mov DSPVersion, AX + + ; Need to detect IRQ/DMA... + + Mov SI, Offset BLASTERString + Mov CX, 7 + Call GetEnvironment ; Returns ES:DI, Carry if error + JC DetectCardNoEnvironment + + Mov BlasterOffset, DI + Mov BlasterSegment, ES + + Cmp IRQ, 0FFFFh + JE DetectCardIRQ3 + Cmp Forced, 0 + JNE DetectCardIRQDone + Jmp DetectCardError + +DetectCardIRQ3: + Push DS + Push SI + + LDS SI, BlasterEnvironment + + Xor DX, DX ; DX = env.. + +DetectCardIRQ1: + LodsB + And AL, AL + JZ DetectCardError + Cmp AL, 'i' + JE DetectCardIRQ2 + Cmp AL, 'I' + JE DetectCardIRQ2 + Jmp DetectCardIRQ1 + +DetectCardIRQ2: + LodsB + And AL, AL + JZ DetectCardIRQEnd + Cmp AL, ' ' + JE DetectCardIRQEnd + Sub AL, '0' + JC DetectCardError + Cmp AL, 9 + JA DetectCardError + + IMul DX, 10 + Add DL, AL + Jmp DetectCardIRQ2 + +DetectCardIRQEnd: + Pop SI + Pop DS + + Mov IRQ, DX + +DetectCardIRQDone: + Cmp DMA, 0FFFFh + JE DetectCardDMA3 + Cmp Forced, 0 + JNE DetectCardDMADone + Jmp DetectCardError + +DetectCardDMA3: + Push DS + Push SI + + LDS SI, BlasterEnvironment + + Xor DX, DX ; DX = env.. + +DetectCardDMA1: + LodsB + And AL, AL + JZ DetectCardError + Cmp AL, 'd' + JE DetectCardDMA2 + Cmp AL, 'D' + JE DetectCardDMA2 + Jmp DetectCardDMA1 + +DetectCardDMA2: + LodsB + And AL, AL + JZ DetectCardDMAEnd + Cmp AL, ' ' + JE DetectCardDMAEnd + Sub AL, '0' + JC DetectCardError + Cmp AL, 9 + JA DetectCardError + + IMul DX, 10 + Add DL, AL + Jmp DetectCardDMA2 + +DetectCardDMAEnd: + Pop SI + Pop DS + + Mov DMA, DX + +DetectCardDMADone: + Mov EAX, 'Jeff' + + ClC + Ret + +DetectCardNoEnvironment: + Cmp DMA, 0FFFFh + JE DetectCardError + Cmp IRQ, 0FFFFh + JNE DetectCardDMADone + +DetectCardError: + StC + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixModeTable Label Word + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix0ModeMono, Mix0ModeStereo + +Proc MixSamples ; Given DS:SI = info tables, CX = numchannels + + ; 1. Clean buffer + ; + update variables + ; 2. Update parameters + ; 3. Mix func + ; 4. Return + + Push CX + + Mov CX, BytesToMix + Mov ES, MixSegment + Mov DI, MIXTABLESIZE + Mov AX, 2020h + + Mov BX, CX ; BX = bytes to mix + Mov DX, CX + + Add CX, CX + + Mov MixTransferOffset, DI ; } Memory write + Cmp CS:Stereo, 0 + JE MixSamples1 + + Mov AX, 1010h + And DX, Not 1 + ShR BX, 1 + ShR CX, 1 + Inc CX + +MixSamples1: + Rep StosW ; } Memory write + Mov MixTransferRemaining, DX ; } + Mov MixLength, BX + + Pop CX + +MixSamples2: + Test Byte Ptr [SI], 1 + JZ MixSamplesEnd2 + Cmp Byte Ptr [SI+36h], 100 + JE MixSamplesEnd2 + + Push CX + Mov CX, [SI] + + Test CH, 2 + JZ MixSamples3 + And Byte Ptr [SI], Not 1 + + Cmp MixMode, 4 ; Is it volume ramping? + JB MixSamplesEnd + +MixSamples3: + Test CL, 20h ; New freq? + JZ MixSamples5 + + Mov AX, [SI+10h] + Mov DX, [SI+12h] + Mov BX, MixSpeed + Cmp DX, BX + JAE MixSamplesHandleError + + Div BX + ShL EAX, 16 + Xor AX, AX + Div BX + Cmp CS:Stereo, 0 + JE MixSampleFreqNoStereo + + ShL EAX, 1 + +MixSampleFreqNoStereo: + Mov STEPVALUE, EAX + +MixSamples4: + Test CH, 1 + JZ MixSamples5 + + Mov DWord Ptr [SI+1Ch], 0 ; Current Volume = 0 + ; for volume sliding. +MixSamples5: + Test CX, 8440h ; New volume or panning? + JZ MixSamplesMix + + Xor AX, AX + Test CH, 8 ; Muted? + JNZ MixModeCommon + + Mov BX, MixMode + Add BL, Stereo + Add BX, BX + Jmp [CS:MixModeTable+BX] + +Mix0Mode: ; 16-bit mixing, no interpolation, no ramping +Mix0ModeMono: + Mov AL, [SI+20h] + ShR AL, 1 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AX, 30 ; Use left only-mixing for mono + Jmp MixModeCommon + +Mix0ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix0ModeSurround + + Mul Byte Ptr [SI+20h] ; Final volume + Add AX, 64 + ShR AX, 7 + Mov [SI+0Ch], AX ; Store into right volume + + Mov AL, 64 + Sub AL, [SI+37h] + Mul Byte Ptr [SI+20h] + Add AX, 64 + ShR AX, 7 + Mov [SI+0Eh], AX ; Left volume + + Mov CH, AL ; CH = left volume + Mov CL, [SI+0Ch] ; CL = right volume + Mov AX, 0 + + Test CX, CX + JZ MixModeCommon + + Mov AX, 30 ; Left only... + Test CL, CL + JZ MixModeCommon + + Mov AX, 60 + Test CH, CH + JZ MixModeCommon + + Mov AX, 90 + Cmp CL, CH + JZ MixModeCommon + + Mov AX, 120 + Jmp MixModeCommon + +Mix0ModeSurround: + Mov AL, [SI+20h] + ShR AL, 2 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AX, 150 ; Surround + Jmp MixModeCommon + +MixModeCommon: ; Requires AX = 30/60/90 etc. depending + ; On mixing mode type. + ; This will add 180 for 16-bit, + ; And sort out loop types. + Mov BL, [SI+0Ah] + Test Byte Ptr [SI+18h], 2 ; 16 bit? + JZ MixModeCommon1 + + Add AX, 180 + +MixModeCommon1: + Cmp BL, 8 + JB MixModeCommon3 ; No loop + JE MixModeCommon2 ; Forwards loop + + Add AX, 10 + +MixModeCommon2: + Add AX, 10 + +MixModeCommon3: + Add AX, Offset MixFunctionTables + Add AX, MixModeOffset + Mov [SI+8], AX ; Offset... + + +MixSamplesMix: + Mov BX, [SI+8] ; BX = offset into + Mov EAX, [CS:BX+2] + Mov DWord Ptr PreMixFunction, EAX + Mov EAX, [CS:BX+6] + Mov DWord Ptr MixFunctionSeparateBackwards, EAX + + Mov AX, MixLength + Mov MixBlockSize, AX + Mov MixBufferOffset, MIXTABLESIZE + + Mov EAX, CURRENTPOSITION + Mov OLDPOSITION, EAX + + Call Word Ptr [CS:BX] + + And Word Ptr [SI], 0111100010001101b + Jmp MixSamplesEnd + +MixSamplesHandleError: + Mov Word Ptr [SI], 200h + + Test Byte Ptr [SI+3Ah], 80h + JNZ MixSamplesEnd + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Turn off channel + +MixSamplesEnd: + Pop CX + +MixSamplesEnd2: + Add SI, 128 + Dec CX + JNZ MixSamples2 + + Ret + +EndP MixSamples + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SBProIRQHandler + + PushAD + Push DS + Push ES + + CLD + + Mov AX, CS + Mov DS, AX + Assume DS:Driver + + Mov DX, BasePort + Add DL, 0Eh + In AL, DX ; 8-bit IRQ ack. + + Mov AL, 20h + Cmp IRQ, 7 + JBE SBProIRQHandler1 + + Out 0A0h, AL + +SBProIRQHandler1: + Out 20h, AL + + Mov AX, MixBufferPos + Mov BX, AX + Mul DMASize + Cmp AX, DMABUFFERLENGTH + JB SBProIRQHandler2 + + Xor AX, AX + Xor BX, BX + +SBProIRQHandler2: + Inc BX + Mov MixBufferPos, BX + + + ; OK... time to get next block + ; Check whether stereo thing is on.. + ; + LES DI, [ActualDMAPtr] + Add DI, AX + + Mov BX, DMASize ; BX = bytes required + + ; BX = samples required + Mov BP, 4 ; Skip for mono + Mov CL, 6 ; Shift for mono + + Cmp Stereo, 0 + JE SBProIRQHandlerMono + + Mov BP, 2 ; Stereo skip value. + Dec CL + +SBProIRQHandlerMono: + Call SaveEMSPageFrame + + Cmp MixTransferRemaining, 0 + JNE SBProIRQHandler4 + Assume DS:Nothing + +SBProIRQHandler3: + Push BX + Push CX + Push BP + Push ES + Push DI + + Call Update + Call MixSamples + + Pop DI + Pop ES + Pop BP + Pop CX + Pop BX + +SBProIRQHandler4: + Mov DS, MixSegment + Mov SI, MixTransferOffset + Mov DX, BX ; DX = samples to transfer + Cmp DX, MixTransferRemaining + JBE SBProIRQHandler5 + + Mov DX, MixTransferRemaining + +SBProIRQHandler5: + Push DX + +SBProIRQHandler6: + Mov AX, [SI] + SAR AX, CL + + Test AH, AH + JNZ SBProIRQHandlerClip1 + +SBProIRQHandler7: + StosB ; } Memory write + + Add SI, BP + Dec DX + JNZ SBProIRQHandler6 + + Pop DX + + Sub MixTransferRemaining, DX ; } Memory write + Sub BX, DX + JNZ SBProIRQHandler3 + + Mov MixTransferOffset, SI ; } Memory write + + Call RestoreEMSPageFrame + + Pop ES + Pop DS + PopAD + IRet + +SBProIRQHandlerClip1: + Mov AL, 00h + JS SBProIRQHandler7 + Mov AL, 0FFh + Jmp SBProIRQHandler7 + + Comment ~ + +Proc SBProIRQHandler + + PushAD + Push DS + Push ES + + CLD + + Mov AX, CS + Mov DS, AX + Assume DS:Driver + + Mov DX, BasePort + Add DL, 0Fh + In AL, DX ; 16-bit IRQ ack. + + Mov AL, 20h + Cmp IRQ, 7 + JBE SBProIRQHandler1 + + Out 0A0h, AL + +SBProIRQHandler1: + Out 20h, AL + + Mov AX, MixBufferPos + Mov BX, AX + Mul DMASize + Cmp AX, DMABUFFERLENGTH + JB SBProIRQHandler2 + + Xor AX, AX + Xor BX, BX + +SBProIRQHandler2: + Inc BX + Mov MixBufferPos, BX + + + ; OK... time to get next block + ; Check whether stereo thing is on.. + ; + LES DI, [ActualDMAPtr] + Add DI, AX + + Mov BX, DMASize ; BX = bytes required + ShR BX, 1 + ; BX = samples required + Mov BP, 4 ; Skip for mono + Mov CL, 6 ; Shift for mono + + Cmp Stereo, 0 + JE SBProIRQHandlerMono + + Mov BP, 2 ; Stereo skip value. + Dec CL + +SBProIRQHandlerMono: + Call SaveEMSPageFrame + + Cmp MixTransferRemaining, 0 + JNE SBProIRQHandler4 + Assume DS:Nothing + +SBProIRQHandler3: + Push BX + Push CX + Push BP + Push ES + Push DI + + Call Update + Call MixSamples + + Pop DI + Pop ES + Pop BP + Pop CX + Pop BX + +SBProIRQHandler4: + Mov DS, MixSegment + Mov SI, MixTransferOffset + Mov DX, BX ; DX = samples to transfer + Cmp DX, MixTransferRemaining + JBE SBProIRQHandler5 + + Mov DX, MixTransferRemaining + +SBProIRQHandler5: + Push DX + Cmp CS:Filter, 1 + JB SBProIRQHandler6 + JE SBProIRQHFilter + + Cmp CS:Stereo, 0 + JE SBProIRQ3QFilterMono + +SBProIRQ3QFilterStereo: + Push BX + + Mov BX, FilterValue + Mov BP, FilterValue2 + ShR DX, 1 + +SBProIRQ3QFilterStereo1: + Mov AX, BX + Mov CX, BP + Add AX, [SI] + Add CX, [SI+2] + SAR AX, 1 + SAR CX, 1 + Add BX, AX + Add BP, CX + SAR BX, 1 + SAR BP, 1 + + Mov AX, BX + SAR AX, 5 + + Test AH, AH + ;...... + +SBProIRQ3QFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL SBPro3QFilterStereoClip3 + Cmp EAX, 7FFFh + JG SBPro3QFilterStereoClip4 + +SBProIRQ3QFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ SBProIRQ3QFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp SBProMixTransferEnd + +SBProIRQ3QFilterMono: + Push BX + + Mov EBX, FilterValue + +SBProIRQ3QFilterMono1: + Mov EAX, EBX + Add EAX, [SI] + SAR EAX, 1 + Add EBX, EAX + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL SBPro3QFilterMonoClip1 + Cmp EAX, 7FFFh + JG SBPro3QFilterMonoClip2 + +SBProIRQ3QFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ SBProIRQ3QFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp SBProMixTransferEnd + +SBProIRQHFilter: + Cmp CS:Stereo, 0 + JE SBProIRQHFilterMono + +SBProIRQHFilterStereo: + Push BX + + Mov EBX, FilterValue + Mov EBP, FilterValue2 + ShR DX, 1 + +SBProIRQHFilterStereo1: + Add EBX, [SI] + Add EBP, [SI+4] + + SAR EBX, 1 + SAR EBP, 1 + + Mov EAX, EBX + SAR EAX, 13 + + Cmp EAX, -8000h + JL SBProHFilterStereoClip1 + Cmp EAX, 7FFFh + JG SBProHFilterStereoClip2 + +SBProIRQHFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL SBProHFilterStereoClip3 + Cmp EAX, 7FFFh + JG SBProHFilterStereoClip4 + +SBProIRQHFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ SBProIRQHFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp SBProMixTransferEnd + +SBProIRQHFilterMono: + Push BX + + Mov EBX, FilterValue + +SBProIRQHFilterMono1: + Add EBX, [SI] + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL SBProHFilterMonoClip1 + Cmp EAX, 7FFFh + JG SBProHFilterMonoClip2 + +SBProIRQHFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ SBProIRQHFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp SBProMixTransferEnd + +SBProIRQHandler6: + Mov EAX, [SI] + SAR EAX, CL + + Cmp EAX, -8000h + JL SBProIRQHandlerClip1 + Cmp EAX, 7FFFh + JG SBProIRQHandlerClip2 + +SBProIRQHandler7: + StosW ; } Memory write + + Add SI, BP + Dec DX + JNZ SBProIRQHandler6 + +SBProMixTransferEnd: + Pop DX + + Sub MixTransferRemaining, DX ; } Memory write + Sub BX, DX + JNZ SBProIRQHandler3 + + Mov MixTransferOffset, SI ; } Memory write + + Call RestoreEMSPageFrame + + Pop ES + Pop DS + PopAD + IRet + +SBProIRQHandlerClip1: + Mov AL, 80h + Jmp SBProIRQHandler7 + +SBProIRQHandlerClip2: + Mov AL, 7Fh + Jmp SBProIRQHandler7 + +SBProHFilterMonoClip1: + Mov AL, 80h + Jmp SBProIRQHFilterMono2 + +SBProHFilterMonoClip2: + Mov AL, 7Fh + Jmp SBProIRQHFilterMono2 + +SBProHFilterStereoClip1: + Mov AL, 80h + Jmp SBProIRQHFilterStereo2 + +SBProHFilterStereoClip2: + Mov AL, 7Fh + Jmp SBProIRQHFilterStereo2 + +SBProHFilterStereoClip3: + Mov AL, 80h + Jmp SBProIRQHFilterStereo3 + +SBProHFilterStereoClip4: + Mov AL, 7Fh + Jmp SBProIRQHFilterStereo3 + +SBPro3QFilterMonoClip1: + Mov AL, 80h + Jmp SBProIRQ3QFilterMono2 + +SBPro3QFilterMonoClip2: + Mov AL, 7Fh + Jmp SBProIRQ3QFilterMono2 + +SBPro3QFilterStereoClip1: + Mov AL, 80h + Jmp SBProIRQ3QFilterStereo2 + +SBPro3QFilterStereoClip2: + Mov AL, 7Fh + Jmp SBProIRQ3QFilterStereo2 + +SBPro3QFilterStereoClip3: + Mov AL, 80h + Jmp SBProIRQ3QFilterStereo3 + +SBPro3QFilterStereoClip4: + Mov AL, 7Fh + Jmp SBProIRQ3QFilterStereo3 + +EndP SBProIRQHandler + Assume DS:Nothing + + ~ + +EndP SBProIRQHandler + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + + PushAD + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Add DI, Offset IRQData + Mov BX, [DI] + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset SBProIRQHandler + + XChg [ES:BX], EAX + Mov OldIRQHandler, EAX + + Mov AX, IMR + And AX, [DI+2] + + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Pop ES + Pop DS + PopAD + + Ret + +EndP SetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIRQ + + PushAD + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Mov BX, [IRQData+DI] + + Mov EAX, OldIRQHandler + Mov [ES:BX], EAX + + Pop ES + Pop DS + PopAD + + Ret + +EndP ResetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StartSBPro ; + + PushA + Push ES + + ; Setup DMA + Mov BX, DMASegment + Xor AX, AX + Mov DX, DMA + Mov DI, DMABUFFERLENGTH + Call SetDMA + + LES DI, ActualDMAPtr + Xor AX, AX + Mov CX, DMABUFFERLENGTH/2 + Rep StosW + + Mov MixBufferPos, 0 + Mov MixTransferRemaining, 0 + + Mov DX, BasePort + Add DL, 0Ch + + Mov AL, 40h ; time constant + Call SBOut + Mov AL, SBMixConst + Call SBOut + + Mov AL, 0D1h ; turn on speaker + Call SBOut + + Mov AL, 48h ; Set DMA Size.. + Call SBOut + Mov AX, DMASize + Dec AX + Call SBOut + Mov AL, AH + Call SBOut + + Mov AL, 1Ch + Cmp MixSpeed, 21739 + JBE StartSBPro1 + + Mov AL, 90h + +StartSBPro1: + Call SBOut + + Pop ES + PopA + + Ret + + Assume DS:Nothing + +EndP StartSBPro + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixerRegisters + + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Pop DS + + Ret + +EndP GetMixerRegisters + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, DS + Mov DriverSegment1, AX + Mov DriverSegment2, AX + Mov DriverSegment3, AX + Mov DriverSegment4, AX + + Call GetEMSPageFrame + Mov EMSPageFrame, AX + + In AL, 0A1h + Mov AH, AL + In AL, 21h + Mov IMR, AX + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + Mov DX, BasePort + Add DL, 4 + + Mov AL, 22h + Call SBGetRegister + Mov AH, AL + And AX, 0FF0h + ShR AL, 4 + ShL AX, 1 + Mov Word Ptr [VolumeTable], AX + + Call GetSBMixConst + + ; Parags to allocate = (4/(.4*31*16))*MixSpeed + 2080 + ; = 661*MixSpeed/65536 + + Mov AX, 1322 + Mul MixSpeed + Add AX, 0FFFFh + AdC DX, 2080 + + Mov BX, (DMABUFFERLENGTH*2)/16 + Add BX, DX + + ; Allocate MixSegment first + Mov AH, 48h + + Int 21h + JNC InitSound1 + +InitSoundNoMemory: + Mov SI, Offset SBProNoMemoryMsg + Ret + +InitSound1: + Mov MixSegment, AX + Add AX, DX + Mov DMASegment, AX + + Call SetIRQ + Call GetTempo + Call SetTempo + Call StartSBPro + + Mov SI, Offset SBProMsg + + Mov AX, BasePort + Mov BX, IRQ + Mov CX, DMA + + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Call ResetIRQ + Call SetIRQ + + Mov SI, Offset ReInitMsg + Mov BX, 40 + Call SetInfoLine + + Mov AX, CS:BasePort + Call ResetDSP + Call StartSBPro + + Pop ES + Pop DS + PopA + + Ret + +EndP ReInitSound + Assume DS:Nothing + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Mov AX, BasePort + Call ResetDSP + + Mov AX, IMR + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Mov AX, MixSegment + Test AX, AX + JZ UnInitSound1 + + Mov ES, AX + Mov AH, 49h ; Release MixSegment + Int 21h + + Call ResetIRQ + +UnInitSound1: + Ret + +EndP UnInitSound + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + Ret + +EndP Poll + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Push AX + Push BX + Push DX + + Push BX + + Mov AX, MixSpeed + Mov BX, AX + Xor DX, DX + + ShL AX, 1 + RCL DX, 1 ; DX:AX = Mixspeed*2 + + ShR BX, 1 ; BX = Mixspeed/2 + + Add AX, BX + AdC DX, 0 ; DX:AX = Mixspeed*2.5 + + Pop BX ; BX = tempo + Div BX + + Mov BytesToMix, AX + + Pop DX + Pop BX + Pop AX + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + PushA + Push DS + + Mov BX, AX ; BX = MixVolume + + Mov AX, CS:MixSegment + Test AX, AX + JZ SetMixVolume2 + + Mov DS, AX + + Mov CX, MIXTABLESIZE/2 + Mov SI, MIXTABLESIZE-2; Starting point - working backwards + +SetMixVolume1: + Mov AX, CX + + Dec AX ; AH = volume, AL = wave value. + Xor DX, DX + XChg AH, DL ; DL = Volume, AX = wave value + CBW + + IMul DX ; DX:AX = Volume * Wave Value + ; Ranges -8192->8128 + + IMul BX ; DX:AX = Volume * Wave Value * Mixing Volume + ; Ranges -1048576->1040384 + + Add AX, 64 + AdC DX, 0 + + ShRD AX, DX, 7 + Mov [SI], AX + Sub SI, 2 + + Loop SetMixVolume1 + +SetMixVolume2: + Pop DS + PopA + + Ret + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + PushA + Mov CX, MixSpeed + + Mov Stereo, AL + Mov AH, AL + + Mov DX, BasePort + Add DL, 4 + + Mov AL, 0Eh ; Stereo register + Out DX, AL + Inc DX + In AL, DX + + Test AH, AH + JZ SBProSetStereo1 + ; Turn on stereo + + ShR CX, 1 + Or AL, 2 + + Jmp SBProSetStereo2 + +SBProSetStereo1: ; Turn off stereo + + And AL, NOT 2 + +SBProSetStereo2: + Mov Frequency, CX + + ClI + + Out DX, AL + Call RecalculateAllFrequencies + + StI + + PopA + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include loadsam.inc + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset SBProScreenList + + ClC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far ; Returns AX, given DI + + Xor AH, AH + Mov AL, [CS:VolumeTable+DI] + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far ; Given AX, DI + + Push DS + Push DX + + Push CS + Pop DS + Assume DS:Driver + + Mov [VolumeTable+DI], AL + + Mov DX, BasePort + Add DL, 4 + Mov AX, Word Ptr [VolumeTable] + + ShL AL, 3 + ShR AH, 1 + And AX, 0FF0h + Or AH, AL + Or AH, 11h + Mov AL, 22h + Out DX, AX + + Pop DX + Pop DS + Ret + +EndP SetVariable + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. + +StopAfterPlay DW 0 +DefaultChannels DW 64 + DW 5 Dup (0) + + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/SNDDRV.ASM b/SoundDrivers/SNDDRV.ASM new file mode 100755 index 0000000..19549fe --- /dev/null +++ b/SoundDrivers/SNDDRV.ASM @@ -0,0 +1,283 @@ + + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +; ÄÄ EmptyFunction ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc EmptyFunction Far + + Xor AX, AX + StC + Ret + +EndP EmptyFunction + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far + + StC + Ret + +EndP DetectCard + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + StC + Ret + +EndP InitSound + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + Ret + +EndP ReInitSound + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Ret + +EndP UnInitSound + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + Ret + +EndP Poll + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + Ret + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load (0 based) +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc LoadSample Far + + StC + Ret + +EndP LoadSample + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release (1 based) +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Xor AX, AX + StC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far + + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far + + Ret + +EndP SetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. +StopAfterPlay DW 0 +DefaultChannels DW 32 + + DW 5 Dup (0) + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/ST97.ASM b/SoundDrivers/ST97.ASM new file mode 100755 index 0000000..e6a5c73 --- /dev/null +++ b/SoundDrivers/ST97.ASM @@ -0,0 +1,866 @@ + + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;*********************************************** + +PNPSERIALID EQU 0FFFFFFFFh +PNPVENDORID EQU 80719304h + +MMT_MAXENTRIES EQU 64 +MMT_MAXSIZE EQU 3*MMT_MAXENTRIES + +ST97Message DB "Sound Track 97 PnP Detected", 13 +; DB "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, ", 0FDh, "Dk RAM", 0 + DB "Port ", 0FDh, "Xh, ", 0FDh, "D Voices, ", 0FDh, "Dk", 0 + +StatusLine DB "FreeST ", 0FDh, "Dk", 0 + +MMTData DW MMT_MAXSIZE Dup (0) + +IRQData Label Word + DW 20h, 1111111111111110b ; IRQ 0 + DW 24h, 1111111111111101b ; IRQ 1 + DW 28h, 1111110111111011b ; IRQ 2 + DW 2Ch, 1111111111110111b ; IRQ 3 + DW 30h, 1111111111101111b ; IRQ 4 + DW 34h, 1111111111011111b ; IRQ 5 + DW 38h, 1111111110111111b ; IRQ 6 + DW 3Ch, 1111111101111111b ; IRQ 7 + DW 1C0h, 1111111011111011b ; IRQ 8 + DW 1C4h, 1111110111111011b ; IRQ 9 + DW 1C8h, 1111101111111011b ; IRQ 10 + DW 1CCh, 1111011111111011b ; IRQ 11 + DW 1D0h, 1110111111111011b ; IRQ 12 + DW 1D4h, 1101111111111011b ; IRQ 13 + DW 1D8h, 1011111111111011b ; IRQ 14 + DW 1DCh, 0111111111111011b ; IRQ 15 + +; ÄÄ EmptyFunction ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc EmptyFunction Far + + Xor AX, AX + StC + Ret + +EndP EmptyFunction + +; ÄÄ ST97InString ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ST97InString ; ES:DI points to deposit point. + ; EAX = memory address + ; CX = count + + ClI + + Mov BL, 2 ; Ctrl=RD_MEM, Data=Memory Address + Call ST97OutDWord + + Mov DX, CS:BasePort ; Length + Mov AX, CX + Call ST97SendByte + + Mov AL, AH + Call ST97SendByte + +ST97InString1: + Call ST97InByte + Cmp AL, 0ABh + JE ST97InStringError + Cmp AL, 0ACh + JNE ST97InString1 + +ST97InString2: + Inc DX + Inc DX + + Rep InsW + + ClC + StI + Ret + +ST97InStringError: + StC + StI + Ret + +EndP ST97InString + +; ÄÄ ST97ReceiveByte ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ST97ReceiveByte ; Returns AL + + Push DX + Mov DX, CS:BasePort + Inc DX + +ST97ReceiveByte1: + In AL, DX + Test AL, AL + JS ST97ReceiveByte1 + + Dec DX + In AL, DX + Pop DX + + Ret + +EndP ST97ReceiveByte + +; ÄÄ ST97InByte ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ST97InByte ; Returns AL + + Jmp ST97ReceiveByte + +EndP ST97InByte + +; ÄÄ ST97InWord ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ST97InWord ; Returns AX + + ClI + + Call ST97ReceiveByte + Mov AL, AH + + Call ST97ReceiveByte + XChg AL, AH + + StI + + Ret + +EndP ST97InWord + +; ÄÄ ST97InDWord ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ST97InDWord ; Returns EAX + + ClI + + Call ST97ReceiveByte + RoR EAX, 8 + + Call ST97ReceiveByte + RoR EAX, 8 + + Call ST97ReceiveByte + RoR EAX, 8 + + Call ST97ReceiveByte + RoR EAX, 8 + + StI + Ret + +EndP ST97InDWord + +; ÄÄ ST97SendByte ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ST97SendByte ; DX = port, AL = data + + Push AX + Push DX + Mov DX, CS:BasePort + Inc DX + +ST97SendByte1: + In AL, DX + Test AL, 40h + JNZ ST97SendByte1 + + Pop DX + Pop AX + + Out DX, AL + + Ret + +EndP ST97SendByte + +; ÄÄ ST97OutByte ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ST97OutByte ; AL = data, AH = command, destroys AX + + ClI + Push DX + + Mov DX, CS:BasePort + Inc DX + + XChg AH, AL + Call ST97SendByte + + Dec DX + + Mov AL, AH + Call ST97SendByte + + Pop DX + StI + + Ret + +EndP ST97OutByte + +; ÄÄ ST97OutWord ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ST97OutWord ; AX = data, BL = command, destroys AX + + ClI + Push DX + Push AX + + Mov DX, CS:BasePort + Mov AL, BL + Inc DX + Call ST97SendByte + + Pop AX + Dec DX + Call ST97SendByte + + Mov AL, AH + Call ST97SendByte + + Pop DX + StI + + Ret + +EndP ST97OutWord + +; ÄÄ ST97OutDWord ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ST97OutDWord ; EAX = data, BL = command + + ClI + Push DX + Push AX + + Mov DX, CS:BasePort + Mov AL, BL + Inc DX + Call ST97SendByte + + Pop AX + Dec DX + Call ST97SendByte + + ShR EAX, 8 + Call ST97SendByte + + ShR EAX, 8 + Call ST97SendByte + + ShR EAX, 8 + Call ST97SendByte + + Pop DX + StI + + Ret + +EndP ST97OutDWord + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +PnP_SerialID DD 0 +PnP_VendorID DD 0 +PnP_ReadPort DW 0 +PnP_CSN DB 0 +PnP_CardFound DB 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetUART ; Given DX = Port + + ClI + + Inc DX + + Mov AL, 0FFh ; Reset! + Out DX, AL + Out DX, AL ; Two resets required to ensure it'll work + + Xor CX, CX + +ResetUART2: + In AL, DX + Test AL, 80h + JNZ ResetUART3 + + Dec DX + In AL, DX + Inc DX + Cmp AL, 0FEh + JE ResetUART4 + +ResetUART3: + Loop ResetUART2 + +ResetUARTError: + StI + StC + Ret + +ResetUART4: ; Now to shove it into 'intelligent' mode. + Xor CX, CX + +ResetUART5: + In AL, DX + Test AL, 40h + LoopNZ ResetUART5 + JNZ ResetUARTError + + Mov AL, 3Fh ; Intelligent mode! + Out DX, AL + +ResetUART6: + Xor CX, CX + +ResetUART7: + In AL, DX + Test AL, 80h + JNZ ResetUART8 + + Dec DX + In AL, DX + Inc DX + Cmp AL, 0FEh + JE ResetUART9 + +ResetUART8: + Loop ResetUART7 + Jmp ResetUARTError + +ResetUART9: + StI + ClC + Ret + +EndP ResetUART + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_Delay + Assume DS:Driver + + Push AX CX + + Mov CX, 180h +PnP_Delay1: + In AL, 21h + Loop PnP_Delay1 + + Pop CX AX + Ret + +EndP PnP_Delay + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_WriteData + + Mov DX, 279h + Out DX, AL + + Mov AL, AH + Mov DH, 0Ah + Out DX, AL + Ret + +EndP PnP_WriteData + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_ReadData + + Mov DX, 279h + Out DX, AL + + Mov DX, PnP_ReadPort + In AL, DX + + Ret + +EndP PnP_ReadData + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_Isolate + + Mov AX, 402h + Call Pnp_WriteData ; Reset CSNs + +PnP_IsolateNextCard: + Mov AX, 0003h + Call PnP_WriteData ; Wake[0] + + Mov AX, PnP_ReadPort + ShL AX, 6 + Xor AL, AL + Call PnP_WriteData ; Set Read Data port. + + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + + Mov AL, 1 ; Serial Isolation + Mov DX, 279h + Out DX, AL + + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + + Mov BL, 6Ah + Mov CX, 64 + Mov DX, PnP_ReadPort + + ClI + +PnP_Isolate1: + ShR PnP_SerialID, 1 + RCR PnP_VendorID, 1 + + Mov BH, BL + ShR BH, 1 + Xor BH, BL + ShR BX, 1 + + In AL, DX + Mov AH, AL + Call PnP_Delay + In AL, DX + Call PnP_Delay + + Cmp AX, 55AAh + JNE PnP_Isolate2 + + Xor BL, 80h + Or PnP_SerialID, 80000000h + +PnP_Isolate2: + Dec CX + JNZ PnP_Isolate1 + + Mov CX, 8 + Xor BH, BH + +PnP_Isolate3: + ShR BH, 1 + + In AL, DX + Mov AH, AL + Call PnP_Delay + In AL, DX + Call PnP_Delay + Cmp AX, 55AAh + JNE PnP_Isolate4 + + Or BH, 80h + +PnP_Isolate4: + Dec CX + JNZ PnP_Isolate3 + + StI + + Cmp BL, BH ; Matching Checksum? + JNE PnP_IsolateFinished + + ; assign CSN + Inc PnP_CSN + + Mov AL, 6 + MOv AH, PnP_CSN + Call PnP_WriteData + + Cmp PnP_VendorID, PNPVENDORID + JNE PnP_IsolateNextCard + Cmp PnP_SerialID, PNPSERIALID + JNE PnP_IsolateNextCard + + Mov AL, 3 + Call PnP_WriteData + Mov AX, 307h ; LDN 3 + Call PnP_WriteData + + Mov AL, 60h + Call PnP_ReadData + Mov AH, AL + Mov AL, 61h + Call PnP_ReadData ; AX = address. + Cmp BasePort, 0FFFFh + JE PnPBasePortOK + + Cmp BasePort, AX + JNE PnP_IsolateNextCard + +PnPBasePortOK: + Mov BasePort, AX + + Mov AL, 70h + Call PnP_ReadData ; AL[3:0] = IRQ + And AX, 15 + JZ PnP_IsolateNextCard + Mov IRQ, AX + + Mov Pnp_CardFound, 1 + Jmp PnP_IsolateNextCard + +PnP_IsolateFinished: + Mov AL, PnP_CSN + ShL AL, 1 + Or AL, PnP_CardFound + + Ret + +EndP PnP_Isolate + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far ; returns carry clear if succesful + + Mov BasePort, 330h + Mov DX, BasePort + Call ResetUART + +; Find memory mapping table + Mov AX, 300h ; Ctrl 3 (GET_MMT), Data 0 + Call ST97OutByte + Call ST97InDWord + + Push CS + Pop ES + Mov CX, MMT_MAXSIZE + Mov DI, Offset MMTData + Call ST97InString + +PnP_DetectEnd: ; Return PnP to wait for key state + Mov EAX, 'Jeff' + + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov SI, Offset ST97Message +Comment ~ + Mov AX, BasePort + Mov BX, IRQ + Mov ECX, DWord Ptr [MMTData+2] + ShR ECX, 9 +~ + Xor BX, BX + Mov AX, 5100h ; Cntrl = GET_VOI, Data = 0 + Call ST97OutByte + Call ST97InByte + Mov BL, AL + Mov AX, BasePort + Mov ECX, DWord Ptr [MMTData+2] + ShR ECX, 9 + + ClC + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + Ret + +EndP ReInitSound + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Mov DX, CS:BasePort + Inc DX + Mov AL, 0FFh + Out DX, AL + + Ret + +EndP UnInitSound + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + Ret + +EndP Poll + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + Ret + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load (0 based) +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc LoadSample Far + + StC + Ret + +EndP LoadSample + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release (1 based) +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + Push CS + Pop DS + Assume DS:Driver + + Mov SI, Offset MMTData+6 + Xor EAX, EAX + +GetStatus1: + Mov CX, [SI] + Add SI, 6 + + Cmp CX, -1 + JE GetStatus2 + + Cmp CX, 1 + JA GetStatus1 + JB GetStatus1 + + Add EAX, [SI+2] + Sub EAX, [SI-4] + Jmp GetStatus1 + +GetStatus2: + Mov SI, Offset StatusLine + ShR EAX, 9 + + ClC + Ret + +EndP GetStatus + Assume DS:Nothing + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Xor AX, AX + StC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far + + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far + + Ret + +EndP SetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 64 ; Maximum number of channels the + ; driver can handle. +StopAfterPlay DW 0 +DefaultChannels DW 64 + + DW 5 Dup (0) + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/ST97CMMX.ASM b/SoundDrivers/ST97CMMX.ASM new file mode 100755 index 0000000..1a3f5fb --- /dev/null +++ b/SoundDrivers/ST97CMMX.ASM @@ -0,0 +1,2773 @@ +; +; ST 97/42 PCI Codec, using MMX. +; + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc +include mmx.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;********************************** + +STEREOENABLED EQU 1 +DMABUFFERLENGTH EQU 8192 +MIXRESOLUTION EQU 32 ; 32 bit mixing +OUTPUTFILTERENABLED EQU 0 +DATAFLAG EQU 200h +ACKFLAG EQU 300h +FOURIERBUFFERLENGTH EQU 2048 ; 2048 samples + +PNPVENDORID EQU 3746630Eh + +FPSave DB 128 Dup (0) + +DMASize DW DMABUFFERLENGTH / 2 + +WSSMsg DB "Sound Track Codec MMX", 13 + DB "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, DMA ", 0FDh, "D", 0 + +WSSNoMemoryMsg DB "Sound Track Codec MMX", 13 + DB "Error: Insufficient memory", 0 + +ReinitMsg DB "Sound Track Codec reinitialised", 0 + +DriverName DB "ITSTCODE.MMX", 0 + +Forced DB 0 +Stereo DB 0 +WSSMixConst DB 0 + +ALIGN 2 + +MixVolume DW 0 + +BytesToMix DW 1000 + +MixSegment DW 0 +FourierSegment DW 0 + +; Arrangement of data: +; First 64 bytes = MMX temporary area +; Next 2*DMABUFFERLENGTH = DMA area +; After that is mixing buffer. + +MixTransferOffset DW 0 +MixTransferRemaining DW 0 + +CONFIGURATIONOFFSET EQU $+128 +CONFIGSIZE EQU 35 +MixMode DW 0 +MixModeOffset DW 0 +VolumeTable DB 56, 56 + DB 60h, 60h, 0Ch ; Low Band + DB 40h, 40h, 1Bh ; Med Low Band + DB 40h, 40h, 72h ; Med High Band + DB 60h, 60h, 40h ; High Band + DB 0, 0, 0 ; Echo + DB 0, 2 ; Surround + DB 0, 90h, 4, 7Fh, 22h ; Reverb + DB 0, 90h, 2, 40h, 9, 3, 13h ; Chorus + DB 0, 0 ; SRS stuff. + +ALIGN 2 + +IMR DW 0 +OldWSSIRQHandler DD 0 + +SAM9407Reset DW 66 + DW 1BEh, 16Fh, 7Fh, 7Fh, ACKFLAG ; Audio in on + DW 1BEh, 168h, 7Fh, 7Fh, ACKFLAG ; Echo on + DW 1BEh, 16Ch, 7Fh, 7Fh, ACKFLAG ; Reverb on + DW 1BEh, 16Dh, 7Fh, 7Fh, ACKFLAG ; Chorus on + DW 1BEh, 16Bh, 0, 0, ACKFLAG ; Equalizer type + DW 1BEh, 16Eh, 7Fh, 7Fh, ACKFLAG ; Surround on + DW 1BEh, 165h, 7Fh, 7Fh ; Post eff on Audio in + DW 1BEh, 166h, 7Fh, 7Fh ; Post eff on reverb, chorus + DW 1BEh, 133h, 0, 0 ; 2 Speaker + DW 1BEh, 120h, 7Fh, 7Fh ; Stereo input 2 + DW 1BEh, 134h, 0FFh, 0FFh ; Left gain + DW 1BEh, 135h, 0FFh, 0FFh ; Right gain + DW 1BEh, 136h, 0, 0 ; Left pan + DW 1BEh, 137h, 7Fh, 7Fh ; Right pan + DW 1BEh, 107h, 0FFh, 0FFh ; Master volume + +SAM9407EqLBL DW 4 + DW 1BEh, 110h, DATAFLAG, 60h +SAM9407EqLBR DW 4 + DW 1BEh, 114h, DATAFLAG, 60h +SAM9407EqLBF DW 4 + DW 1BEh, 118h, DATAFLAG, 0Ch +SAM9407EqMLBL DW 4 + DW 1BEh, 111h, DATAFLAG, 40h +SAM9407EqMLBR DW 4 + DW 1BEh, 115h, DATAFLAG, 40h +SAM9407EqMLBF DW 4 + DW 1BEh, 119h, DATAFLAG, 1Bh +SAM9407EqMHBL DW 4 + DW 1BEh, 112h, DATAFLAG, 40h +SAM9407EqMHBR DW 4 + DW 1BEh, 116h, DATAFLAG, 40h +SAM9407EqMHBF DW 4 + DW 1BEh, 11Ah, DATAFLAG, 72h +SAM9407EqHBL DW 4 + DW 1BEh, 113h, DATAFLAG, 60h +SAM9407EqHBR DW 4 + DW 1BEh, 117h, DATAFLAG, 60h +SAM9407EqHBF DW 4 + DW 1BEh, 11Bh, DATAFLAG, 0Ch +SAM9407EchoLevel DW 4 + DW 1BEh, 128h, DATAFLAG, 0 +SAM9407EchoTime DW 4 + DW 1BEh, 129h, DATAFLAG, 2Bh +SAM9407EchoFeed DW 4 + DW 1BEh, 12Ah, DATAFLAG, 40h +SAM9407SurroundVolume DW 4 + DW 1BEh, 130h, DATAFLAG, 0 +SAM9407SurroundDelay DW 4 + DW 1BEh, 131h, DATAFLAG, 2 +SAM9407ReverbSend DW 4 + DW 1BEh, 127h, DATAFLAG, 0 +SAM9407ReverbVolume DW 3 + DW 1BEh, 13Ah, DATAFLAG +SAM9407ReverbType DW 4 + DW 1BEh, 169h, DATAFLAG, 4 +SAM9407ReverbTime DW 3 + DW 1BEh, 178h, DATAFLAG +SAM9407ReverbFeedback DW 3 + DW 1BEh, 179h, DATAFLAG +SAM9407ChorusSend DW 4 + DW 1BEh, 124h, DATAFLAG, 0 +SAM9407ChorusVolume DW 3 + DW 1BEh, 13Bh, DATAFLAG +SAM9407ChorusType DW 4 + DW 1BEh, 16Ah, DATAFLAG, 2 +SAM9407ChorusDelay DW 3 + DW 1BEh, 174h, DATAFLAG +SAM9407ChorusFeedback DW 3 + DW 1BEh, 175h, DATAFLAG +SAM9407ChorusRate DW 3 + DW 1BEh, 176h, DATAFLAG +SAM9407ChorusDepth DW 3 + DW 1BEh, 177h, DATAFLAG +SAM9407Mono DW 4 + DW 1BEh, 132h, 7Fh, 0 +SAM9407Stereo DW 4 + DW 1BEh, 132h, 0, 0 + +SAM9407Strings DW Offset SAM9407Reset ;1 + DW Offset SAM9407EqLBL, Offset SAM9407EqLBR + DW Offset SAM9407EqLBF + DW Offset SAM9407EqMLBL, Offset SAM9407EqMLBR + DW Offset SAM9407EqMLBF + DW Offset SAM9407EqMHBL, Offset SAM9407EqMHBR + DW Offset SAM9407EqMHBF + DW Offset SAM9407EqHBL, Offset SAM9407EqHBR + DW Offset SAM9407EqHBF + DW Offset SAM9407EchoLevel ; 14 + DW Offset SAM9407EchoTime + DW Offset SAM9407EchoFeed + DW Offset SAM9407SurroundVolume ; 17 + DW Offset SAM9407SurroundDelay + DW Offset SAM9407ReverbSend ; 19 + DW Offset SAM9407ReverbVolume + DW Offset SAM9407ReverbType + DW Offset SAM9407ReverbTime + DW Offset SAM9407ReverbFeedback ; 23 + DW Offset SAM9407ChorusSend ; 24 + DW Offset SAM9407ChorusVolume + DW Offset SAM9407ChorusType + DW Offset SAM9407ChorusDelay + DW Offset SAM9407ChorusFeedback + DW Offset SAM9407ChorusRate + DW Offset SAM9407ChorusDepth ; 30 + DW Offset SAM9407Mono ; 31 + DW Offset SAM9407Stereo + +MixSpeedTable DW 5513, 41h + DW 6615, 4Fh + DW 8000, 40h + DW 9600, 4Eh + DW 11025, 43h + DW 16000, 42h + DW 18900, 45h + DW 22050, 47h + DW 27429, 44h + DW 32000, 46h + DW 33075, 4Dh + DW 37800, 49h + DW 44100, 4Bh + DW 48000, 4Ch + DW 54860, 48h + DW 64000, 4Ah + +IRQData Label Word + DW 20h, 1111111111111110b ; IRQ 0 + DW 24h, 1111111111111101b ; IRQ 1 + DW 28h, 1111110111111011b ; IRQ 2 + DW 2Ch, 1111111111110111b ; IRQ 3 + DW 30h, 1111111111101111b ; IRQ 4 + DW 34h, 1111111111011111b ; IRQ 5 + DW 38h, 1111111110111111b ; IRQ 6 + DW 3Ch, 1111111101111111b ; IRQ 7 + DW 1C0h, 1111111011111011b ; IRQ 8 + DW 1C4h, 1111110111111011b ; IRQ 9 + DW 1C8h, 1111101111111011b ; IRQ 10 + DW 1CCh, 1111011111111011b ; IRQ 11 + DW 1D0h, 1110111111111011b ; IRQ 12 + DW 1D4h, 1101111111111011b ; IRQ 13 + DW 1D8h, 1011111111111011b ; IRQ 14 + DW 1DCh, 0111111111111011b ; IRQ 15 + +;********************************** +; WSS Registers +;********************************** + +CODEC_INDEX_LIC = 00 +CODEC_INDEX_RIC = 01h +CODEC_INDEX_LX1C = 02h +CODEC_INDEX_RX1C = 03h +CODEC_INDEX_LX2C = 04h +CODEC_INDEX_RX2C = 05h +CODEC_INDEX_LDC = 06h +CODEC_INDEX_RDC = 07h +CODEC_INDEX_CDF = 08h +CODEC_INDEX_INTF = 09h +CODEC_INDEX_PIN = 0Ah +CODEC_INDEX_TEST = 0Bh +CODEC_INDEX_MISC = 0Ch +CODEC_INDEX_DIGMIX = 0Dh +CODEC_INDEX_UPR_COUNT = 0Eh +CODEC_INDEX_LWR_COUNT = 0Fh + +CODEC_MCE = 40h + +LDC_LDM = 80h +LDC_LDA = 3Fh + +RDC_RDM = 80h +RDC_RDA = 3Fh + +CDF_STEREO = 10h + +INTF_PEN = 01h +INTF_CEN = 02h +INTF_SDC = 04h +INTF_ACAL = 08h +INTF_PPIO = 40h +INTF_CPIO = 80h + +PIN_IEN = 2 + +TEST_ORL = 03h +TEST_ORR = 0Ch +TEST_DRS = 10h +TEST_ACI = 20h +TEST_PUR = 40h +TEST_COR = 80h + +;********************************** + +WSS16ScreenList Label + DW 16 + DW Near Ptr IdleFunctionList + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr WSSHeaderLine + + DW Near Ptr DriverText + + DW Near Ptr MixModeText + DW Near Ptr MixModeButton1 ; 6 + DW Near Ptr MixModeButton2 ; + DW Near Ptr MixModeButton3 ; + DW Near Ptr MixModeButton4 ; + + DW Near Ptr EmptyObject + DW Near Ptr EmptyObject + DW Near Ptr EmptyObject + DW Near Ptr EmptyObject + + DW Near Ptr VolumeText + DW Near Ptr VolumeBox1 + + DW Near Ptr MasterVolumeLeft ; 16 + DW Near Ptr MasterVolumeRight ; 17 + + DW Near Ptr CS4237SRSCenter ; 18 + DW Near Ptr CS4237SRSSpace ; 19 + DW Near Ptr CSControlPortText + +ST42A DW Near Ptr SAM9407PortText ; 21 + DW Near Ptr SAM9407ParametersText + DW Near Ptr SAM9407ParametersBox + + DW Near Ptr EqLBL ; 24 + DW Near Ptr EqLBR + DW Near Ptr EqLBF + + DW Near Ptr EqMLBL + DW Near Ptr EqMLBR + DW Near Ptr EqMLBF + + DW Near Ptr EqMHBL + DW Near Ptr EqMHBR + DW Near Ptr EqMHBF + + DW Near Ptr EqHBL + DW Near Ptr EqHBR + DW Near Ptr EqHBF + + DW Near Ptr EchoLevel ; 33 + DW Near Ptr EchoTime + DW Near Ptr EchoFeedback + + DW Near Ptr SurroundVolume + DW Near Ptr SurroundDelay + + DW Near Ptr ReverbSend ; 38 + DW Near Ptr ReverbVolume + DW Near Ptr ReverbType + DW Near Ptr ReverbTime + DW Near Ptr ReverbFeedback + + DW Near Ptr ChorusSend + DW Near Ptr ChorusVolume + DW Near Ptr ChorusType + DW Near Ptr ChorusDelay + DW Near Ptr ChorusFeedback + DW Near Ptr ChorusRate + DW Near Ptr ChorusDepth + + + DW 0 + +WSSHeaderLine DW 10 + DB "Sound Track Codec Driver", 0 + +EmptyObject DW 1 + DB 0, 0 + DB 0 + DB 0 + +DriverText DW 1 + DB 28, 48 + DB 21h + DB "Sound Track Codec Driver 1.0 for Impulse Tracker", 0 + +CSControlPortText DW 1 + DB 28, 47 + DB 21h + DB "Sound Track CS4237 Control Port ", 0FDh, "Xh", 0 +CS4237Port DW 0 + +SAM9407PortText DW 1 + DB 28, 46 + DB 21h + DB "Sound Track SAM9407 Port ", 0FDh, "Xh", 0 +SAM9407Port DW 0 + +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +IdleFunctionList DD 0 + DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +VolumeText DW 1 + DB 2, 14 + DB 20h + DB "Master Volume Left", 13 + DB "Master Volume Right", 13 + DB "CS4237 SRS Center", 13 + DB "CS4237 SRS Space" + DB 0 + +VolumeBox1 DW 0 + DB 21, 13, 31, 18 + DB 25 + +MasterVolumeLeft DW 14 + DB 22, 14 + DW 0, 63 + DW 9, 0 + DW 0FFFFh, 17, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 8 + +MasterVolumeRight DW 14 + DB 22, 15 + DW 0, 63 + DW 9, 1 + DW 16, 18, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 8 + +CS4237SRSCenter DW 14 + DB 22, 16 + DW 0, 15 + DW 9, 31 + DW 17, 19, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 8 + +CS4237SRSSpace DW 14 + DB 22, 17 + DW 0, 15 + DW 9, 32 + DW 18, 6, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 8 + +MixModeText DW 1 + DB 2, 19 + DB 20h + DB "Mixing Rate: ", 0FDh, "D", 0 +MixSpeed DW 48000 + DW 0 + +MixModeButton1 DW 2 + DW 19, 7, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment1 DW 0 + DW 0 + DW Offset SetMixMode +DriverSegment2 DW 0 + DB 3, 21, 32, 23, 8 + DB 0 + DB " MMX, Non-interpolated", 0 + +MixModeButton2 DW 2 + DW 6 + DW 8, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment3 DW 0 + DW 1 + DW Offset SetMixMode +DriverSegment4 DW 0 + DB 3, 24, 32, 26, 8 + DB 0 + DB " MMX, Interpolated", 0 + +MixModeButton3 DW 2 + DW 7, 9, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment5 DW 0 + DW 2 + DW Offset SetMixMode +DriverSegment6 DW 0 + DB 3, 27, 32, 29, 8 + DB 0 + DB " MMX, Volume Ramp", 0 + +MixModeButton4 DW 2 + DW 8 +ST42B DW 24, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment7 DW 0 + DW 3 + DW Offset SetMixMode +DriverSegment8 DW 0 + DB 3, 30, 32, 32, 8 + DB 0 + DB " MMX, Filtered", 0 + +SAM9407ParametersText DW 1 + DB 36, 14 + DB 20h + DB "Low Band Left", 13 + DB "Low Band Right", 13 + DB "Low Band Frequency", 13 + DB "Med Low Band Left", 13 + DB "Med Low Band Right", 13 + DB "Med Low Band Frequency", 13 + DB "Med High Band Left", 13 + DB "Med High Band Right", 13 + DB "Med High Band Frequency", 13 + DB "High Band Left", 13 + DB "High Band Right", 13 + DB "High Band Frequency", 13 + DB "Echo Level", 13 + DB "Echo Time", 13 + DB "Echo Feedback", 13 + DB "Surround Volume", 13 + DB "Surround Delay", 13 + DB "Reverb Send", 13 + DB "Reverb Volume", 13 + DB "Reverb Type", 13 + DB "Reverb Time", 13 + DB "Reverb Feedback", 13 + DB "Chorus Send", 13 + DB "Chorus Volume", 13 + DB "Chorus Type", 13 + DB "Chorus Delay", 13 + DB "Chorus Feedback", 13 + DB "Chorus Rate", 13 + DB "Chorus Depth", 13 + DB 0 + +EqLBL DW 14 + DB 60, 14 + DW 0, 127 + DW 9, 2 + DW 9, 25, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqLBR DW 14 + DB 60, 15 + DW 0, 127 + DW 9, 3 + DW 24, 26, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqLBF DW 14 + DB 60, 16 + DW 0, 127 + DW 9, 4 + DW 25, 27, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqMLBL DW 14 + DB 60, 17 + DW 0, 127 + DW 9, 5 + DW 26, 28, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqMLBR DW 14 + DB 60, 18 + DW 0, 127 + DW 9, 6 + DW 27, 29, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqMLBF DW 14 + DB 60, 19 + DW 0, 127 + DW 9, 7 + DW 28, 30, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqMHBL DW 14 + DB 60, 20 + DW 0, 127 + DW 9, 8 + DW 29, 31, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqMHBR DW 14 + DB 60, 21 + DW 0, 127 + DW 9, 9 + DW 30, 32, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqMHBF DW 14 + DB 60, 22 + DW 0, 127 + DW 9, 10 + DW 31, 33, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqHBL DW 14 + DB 60, 23 + DW 0, 127 + DW 9, 11 + DW 32, 34, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqHBR DW 14 + DB 60, 24 + DW 0, 127 + DW 9, 12 + DW 33, 35, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqHBF DW 14 + DB 60, 25 + DW 0, 127 + DW 9, 13 + DW 34, 36, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EchoLevel DW 14 + DB 60, 26 + DW 0, 127 + DW 9, 15 + DW 35, 37, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EchoTime DW 14 + DB 60, 27 + DW 0, 127 + DW 9, 14 + DW 36, 38, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EchoFeedback DW 14 + DB 60, 28 + DW 0, 127 + DW 9, 16 + DW 37, 39, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +SurroundVolume DW 14 + DB 60, 29 + DW 0, 255 + DW 9, 17 + DW 38, 40, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +SurroundDelay DW 14 + DB 60, 30 + DW 0, 127 + DW 9, 18 + DW 39, 41, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ReverbSend DW 14 + DB 60, 31 + DW 0, 127 + DW 9, 19 + DW 40, 42, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ReverbVolume DW 14 + DB 60, 32 + DW 0, 255 + DW 9, 20 + DW 41, 43, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + + +ReverbType DW 14 + DB 60, 33 + DW 0, 7 + DW 9, 21 + DW 42, 44, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ReverbTime DW 14 + DB 60, 34 + DW 0, 127 + DW 9, 22 + DW 43, 45, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ReverbFeedback DW 14 + DB 60, 35 + DW 0, 127 + DW 9, 23 + DW 44, 46, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ChorusSend DW 14 + DB 60, 36 + DW 0, 127 + DW 9, 24 + DW 45, 47, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ChorusVolume DW 14 + DB 60, 37 + DW 0, 255 + DW 9, 25 + DW 46, 48, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ChorusType DW 14 + DB 60, 38 + DW 0, 7 + DW 9, 26 + DW 47, 49, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ChorusDelay DW 14 + DB 60, 39 + DW 0, 127 + DW 9, 27 + DW 48, 50, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ChorusFeedback DW 14 + DB 60, 40 + DW 0, 127 + DW 9, 28 + DW 49, 51, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ChorusRate DW 14 + DB 60, 41 + DW 0, 127 + DW 9, 29 + DW 50, 52, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ChorusDepth DW 14 + DB 60, 42 + DW 0, 127 + DW 9, 30 + DW 51, 0FFFFh, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +SAM9407ParametersBox DW 0 + DB 59, 13, 75, 43 + DB 25 + +; ÄÄ MixingRoutines ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + + +include dmasirq.inc +include mix.inc + +include m32bitm.mix +include m32bitmi.mix +include m32bitmv.mix +include m32bitmf.mix + +ALIGN 2 + +MixFunctionTables Label +include m32bitm.inc +include m32bitmi.inc +include m32bitmv.inc +include m32bitmf.inc +include mnomix.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +RelocationTable Label Word + DW Offset DriverSegment1, Offset DriverSegment2 + DW Offset DriverSegment3, Offset DriverSegment4 + DW Offset DriverSegment5, Offset DriverSegment6 + DW Offset DriverSegment7, Offset DriverSegment8 + DW 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixMode Far + + Push CS + Pop ES + Mov DI, Offset MixMode + + Ret + +EndP GetMixMode + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WaitCoDec + + Push CX + + Mov CX, 0F000h + +WaitCoDec1: + In AL, DX + Test AL, AL + JNS WaitCoDec2 + Loop WaitCoDec1 + + StC + +WaitCoDec2: + Pop CX + Ret + +EndP WaitCoDec + +; ÄÄ SAM9407InByte ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SAM9407InByte ; Returns AL + + Push DX + Mov DX, CS:SAM9407Port + Inc DX + +SAM9407InByte1: + In AL, DX + Test AL, AL + JS SAM9407InByte1 + + Dec DX + In AL, DX + Pop DX + + Ret + +EndP SAM9407InByte + +; ÄÄ ST97SendByte ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SAM9407SendByte ; DX = port, AL = data + + Push AX + Push DX + Mov DX, CS:SAM9407Port + Inc DX + +SAM9407SendByte1: + In AL, DX + Test AL, 40h + JNZ SAM9407SendByte1 + + Pop DX + Pop AX + + Out DX, AL + + Ret + +EndP SAM9407SendByte + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetSAM9407 ; DI = index. 1 = full reinit. + + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + LEA SI, [SAM9407Strings+EDI+EDI-2] + Mov SI, [SI] + + LodsW + Mov CX, AX + +SetSAM9407_1: +; AH = 0 = normal data, 1 = command, 2 = param, 3 = ack. + + Mov DX, SAM9407Port + Test DX, DX + JZ NoSAM9407 + + LodsW + + Cmp AH, 2 + JB SetSAM9407_3 + JA SetSAM9407_4 + + Mov AL, [VolumeTable+DI] + Jmp SetSAM9407_2 + +SetSAM9407_4: + Call SAM9407InByte + Test AL, AL + JNZ SetSAM9407_4 + Jmp SetSAM9407_5 + +SetSAM9407_3: + And AH, 1 + Add DL, AH + +SetSAM9407_2: + Call SAM9407SendByte + +SetSAM9407_5: + Dec CX + JNZ SetSAM9407_1 + + +NoSAM9407: + Pop DS + PopA + + Ret + +EndP SetSAM9407 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WaitAutoCalibration + + Push CX + Mov CX, 0F000h + +WaitAutoCalibration1: + Mov AL, CODEC_INDEX_TEST + Out DX, AL + Inc DX + In AL, DX + Dec DX + Test AL, TEST_ACI + JNZ WaitAutoCalibration2 + Loop WaitAutoCalibration1 + + StC + +WaitAutoCalibration2: + Pop CX + Ret + +EndP WaitAutoCalibration + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixMode Far + + Mov AX, [SI+22] + + ClI + + Mov CS:MixMode, AX + + Mov BX, 60 + Mul BX + Mov CS:MixModeOffset, AX + + StI + Mov AX, 1 + Ret + +EndP SetMixMode + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetWSSMixConst ; Work out value.. and nearest + ; mixspeed value. + + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, CmdLineMixSpeed + Mov CX, MixSpeed + Test AX, AX + JZ GetWSSMixConst1 + + Mov CX, 64000 + Cmp AX, CX + JA GetWSSMixConst1 + + Mov CX, 8000 + Cmp AX, CX + JB GetWSSMixConst1 + + Mov CX, AX + +GetWSSMixConst1: ; CX = desired mixspeed + Mov SI, Offset MixSpeedTable + Mov DX, 16 ; 16 different available speeds + + Xor BX, BX + +GetWSSMixConst2: + LodsW + Cmp AX, BX + JB GetWSSMixConst3 + Cmp AX, CX + JA GetWSSMixConst3 + + Mov BX, AX + Mov DH, [SI] + +GetWSSMixConst3: + LodsW ; Add SI, 2 + Dec DL + JNZ GetWSSMixConst2 + + Mov MixSpeed, BX + Mov WSSMixConst, DH + + FNInit + FILd DWord Ptr [MixSpeed] + FMul FreqMultiplier + FStP FreqMultiplier + + Mov AX, BX + Mov BX, 12000 + Xor DX, DX + Div BX + Mov FourierBufferStepOffset, AX + Mov FourierBufferStepFractional, DX + + Pop DS + PopA + Ret + +EndP GetWSSMixConst + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PingWSS ; Check BasePort, DX = BasePort + ; Preserves DX, destroys AX + + Push DX + + Add DX, 6 + + + In AL, DX + Xor AL, AL + Out DX, AL + + Dec DX + Dec DX + Call WaitCodec + JC PingWSSFailure + + In AL, DX + Test AL, AL + JS PingWSSFailure + + Mov AL, CODEC_INDEX_MISC + Out DX, AL + Inc DX ; DX = Data port + In AL, DX + Mov AH, AL ; AH = Revision + + Xor AL, AL ; Write 0 revision + Out DX, AL + In AL, DX + And AX, 8F8Fh + Cmp AL, AH + JNE PingWSSFailure + Dec DX ; DX = AD1848 baseport + + Mov AL, CODEC_MCE or CODEC_INDEX_INTF + Out DX, AL + Inc DX + Mov AL, INTF_ACAL or INTF_SDC + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_INTF + Out DX, AL + Inc DX + Mov AL, INTF_ACAL or INTF_SDC + Out DX, AL + Dec DX + + Call WaitAutoCalibration ; Returns carry if error + ; Carry clear if none. + + DB 85h + +PingWSSFailure: + StC + Pop DX + + Ret + + +EndP PingWSS + +include nodebug.inc + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +PnP_SerialID DD 0 +PnP_VendorID DD 0 +PnP_ReadPort DW 0 +PnP_CSN DB 0 +PnP_CardFound DB 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectMMX + + PushFD + Pop EAX + Mov EBX, EAX + Xor EAX, 00200000h + Push EAX + PopFD + PushFD + Pop EAX + Cmp EAX, EBX + JZ DetectMMXFail + + Mov EAX, 1 + DB 0Fh, 0A2h ; CPUID + Test EDX, 800000h + JZ DetectMMXFail + + Trace "MMX Detected" + + DB 85h + +DetectMMXFail: + StC + Ret + +EndP DetectMMX + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_Delay + Assume DS:Driver + + Push AX CX + + Mov CX, 180h +PnP_Delay1: + In AL, 21h + Loop PnP_Delay1 + + Pop CX AX + Ret + +EndP PnP_Delay + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_WriteData + + Mov DX, 279h + Out DX, AL + + Mov AL, AH + Mov DH, 0Ah + Out DX, AL + Ret + +EndP PnP_WriteData + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_ReadData + + Mov DX, 279h + Out DX, AL + + Mov DX, PnP_ReadPort + In AL, DX + + Ret + +EndP PnP_ReadData + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_Isolate + + Mov AX, 402h + Call Pnp_WriteData ; Reset CSNs + +PnP_IsolateNextCard: + Mov AX, 0003h + Call PnP_WriteData ; Wake[0] + + Mov AX, PnP_ReadPort + ShL AX, 6 + Xor AL, AL + Call PnP_WriteData ; Set Read Data port. + + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + + Mov AL, 1 ; Serial Isolation + Mov DX, 279h + Out DX, AL + + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + + Mov BL, 6Ah + Mov CX, 64 + Mov DX, PnP_ReadPort + + ClI + +PnP_Isolate1: + ShR PnP_SerialID, 1 + RCR PnP_VendorID, 1 + + Mov BH, BL + ShR BH, 1 + Xor BH, BL + ShR BX, 1 + + In AL, DX + Mov AH, AL + Call PnP_Delay + In AL, DX + Call PnP_Delay + + Cmp AX, 55AAh + JNE PnP_Isolate2 + + Xor BL, 80h + Or PnP_SerialID, 80000000h + +PnP_Isolate2: + Dec CX + JNZ PnP_Isolate1 + + Mov CX, 8 + Xor BH, BH + +PnP_Isolate3: + ShR BH, 1 + + In AL, DX + Mov AH, AL + Call PnP_Delay + In AL, DX + Call PnP_Delay + Cmp AX, 55AAh + JNE PnP_Isolate4 + + Or BH, 80h + +PnP_Isolate4: + Dec CX + JNZ PnP_Isolate3 + + StI + + Cmp BL, BH ; Matching Checksum? + JNE PnP_IsolateFinished + + ; assign CSN + Inc PnP_CSN + + Mov AL, 6 + MOv AH, PnP_CSN + Call PnP_WriteData + + Cmp PnP_VendorID, PNPVENDORID + JNE PnP_IsolateNextCard +; Cmp PnP_SerialID, PNPSERIALID +; JNE PnP_IsolateNextCard + + Mov AL, 3 + Call PnP_WriteData + + Mov AX, 007h ; Configuration device + Call PnP_WriteData + + Mov AL, 60h + Call PnP_ReadData + Mov AH, AL + Mov AL, 61h + Call PnP_ReadData ; AX = address. + + Test AX, AX + JZ PnP_IsolateNextCard + + Cmp BasePort, 0FFFFh + JE PnPBasePortOK + + Cmp BasePort, AX + JNE PnP_IsolateNextCard + +PnPBasePortOK: + Mov BasePort, AX + + Mov AL, 70h + Call PnP_ReadData ; AL[3:0] = IRQ + And AX, 15 + JZ PnP_IsolateNextCard + Mov IRQ, AX + + Mov AL, 74h + Call PnP_ReadData ; AL[2:0] = DMA + And AX, 7 + Cmp AL, 4 + JE PnP_IsolateNextCard + Mov DMA, AX + + Mov AX, 207h ; CS4237 + Call PnP_WriteData + + Mov AL, 60h + Call PnP_ReadData + Mov AH, AL + Mov AL, 61h + Call PnP_ReadData ; AX = address. + Test AX, AX + JZ PnP_IsolateNextCard + + Mov CS4237Port, AX + + Mov AX, 407h ; SAM9407 + Call PnP_WriteData + + Mov AL, 60h + Call PnP_ReadData + Mov AH, AL + Mov AL, 61h + Call PnP_ReadData ; AX = address. + Test AX, AX + JZ PnP_NoSAM9407 + + Mov SAM9407Port, AX + + Mov Pnp_CardFound, 1 + Jmp PnP_IsolateNextCard + +Pnp_NoSAM9407: + Xor AX, AX + Mov SAM9407Port, AX + Mov ST42A, AX + Dec AX + Mov ST42B, AX + Mov Pnp_CardFound, 1 + Jmp PnP_IsolateNextCard + + +PnP_IsolateFinished: + Mov AL, PnP_CSN + ShL AL, 1 + Or AL, PnP_CardFound + + Ret + +EndP PnP_Isolate + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far ; returns carry clear if succesful + + Call DetectMMX + JC DetectWSSFailure + + Push CS + Pop DS + + Xor AL, AL + Mov DX, 279h + Out DX, AL + Out DX, AL + + Mov AL, 6Ah ; Starting value + Mov CX, 32 + +PnP_InitiationKeyLoop: + Out DX, AL + + Mov AH, AL + ShR AH, 1 + Xor AH, AL + ShR AX, 1 + + Dec CX + JNZ PnP_InitiationKeyLoop + +; Try three ports before concluding no PnP cards: 20Fh, 27Bh, 213h + +PnP_DetectCardPort1: + Mov PnP_ReadPort, 20Fh + Call PnP_Isolate + JZ PnP_DetectCardPort2 + Test AL, 1 + JZ PnP_DetectCardNotFound + Jmp PnP_DetectCardFound + +PnP_DetectCardPort2: + Mov PnP_ReadPort, 27Bh + Call PnP_Isolate + JZ PnP_DetectCardPort3 + Test AL, 1 + JZ PnP_DetectCardNotFound + Jmp PnP_DetectCardFound + +PnP_DetectCardPort3: + Mov PnP_ReadPort, 213h + Call PnP_Isolate + Test AL, 1 + JNZ PnP_DetectCardFound + +PnP_DetectCardNotFound: + StC + Jmp PnP_DetectEnd + +PnP_DetectCardFound: + ClC + +PnP_DetectEnd: ; Return PnP to wait for key state + Mov AX, 202h + Call PnP_WriteData + Mov DX, BasePort + JNC BasePortNotSpecified +; JNC DetectWSSOK + +DetectPCI: +; Cmp DMA, 0FFFFh +; JNE DMAOverride + + Mov DMA, 1 ; Force DMA to 1. + +DMAOverride: + Mov EBX, 80000000h ; PCI output value. + Mov DX, 0CF8h + Mov CX, 32 + +DetectCardPCIBasePort1: + Mov EAX, EBX + Out DX, EAX + Add DX, 4 + In EAX, DX + Sub DX, 4 + Add EBX, 1 SHL 11 + + Cmp EAX, 8128Eh + LoopNE DetectCardPCIBasePort1 + + JNE DetectWSSFailure + + Add EBX, (3Ch) - (1 SHL 11) + Mov EAX, EBX + Out DX, EAX + Add DX, 4 + In EAX, DX ; AL = IRQ + Mov ECX, EAX + And AX, 0FFh + + JZ DetectWSSFailure + Cmp AL, 15 + JA DetectWSSFailure + + Cmp IRQ, 0FFFFh + JNE IRQSpecified + + Mov IRQ, AX + +IRQSpecified: + Sub DX, 4 + +; Get SAM9407IRQ + Add EBX, 1 SHL 8 + Mov EAX, EBX + Out DX, EAX + Add DX, 4 + In EAX, DX + Sub DX, 4 ; AL = IRQ. + + And AX, 0FFh + + PushA + + JZ NoSAM9407IRQ + Cmp AL, 15 + JA NoSAM9407IRQ + + Mov DL, AL + ShL DL, 4 + Mov CL, AL + And DX, 80h + Mov CH, 1 + Or DL, 21h + And CL, 7 + ShL CH, CL + In AL, DX + Or AL, CH + Out DX, AL + +NoSAM9407IRQ: + PopA + Push AX + + Add EBX, 10h-3Ch ; SAM9407 port + Mov EAX, EBX + Out DX, EAX + Add DX, 4 + In EAX, DX + Sub DX, 4 + And AX, 0FFEh + Mov SAM9407Port, AX + Pop CX + +; If SAM9407 Port not available, or IRQ = old IRQ, then set to ST42 mode. + Test AX, AX + JZ ST42Found + Cmp AX, 400h + JA ST42Found + Cmp CX, IRQ + JNE NoST42 + +ST42Found: +; Mov AX, '24' +; Mov Word Ptr O97A, AX +; Mov Word Ptr O97B, AX +; Mov Word Ptr O97C, AX +; Mov Word Ptr O97D, AX +; Mov Word Ptr O97E, AX +; Mov Word Ptr O97F, AX + Xor AX, AX + Mov SAM9407Port, AX + Mov ST42A, AX + Dec AX + Mov ST42B, AX + +NoST42: + Add EBX, 3 SHL 8 + Mov EAX, EBX + Out DX, EAX + Add DX, 4 + In EAX, DX + Sub DX, 4 + And AX, 0FFEh + Cmp AX, 400h + JB NoCS + + Xor AX, AX + +NoCS: + Mov CS4237Port, AX + + Sub EBX, 4 SHL 8 + +; Add EBX, 10h - 3Ch +; Add EBX, (10h) - (1 SHL 11) + Mov EAX, EBX + Out DX, EAX + Add DX, 4 + In EAX, DX + + And AX, 0FFEh + Mov DX, AX + + Cmp BasePort, 0FFFFh + JE BasePortNotSpecified + + Mov DX, BasePort + +BasePortnotSpecified: + Call PingWSS + JNC DetectWSSOK + + Sub DX, 4 + Call PingWSS + JNC DetectWSSOK + +DetectWSSFailure: + StC + Ret + +DetectWSSOK: + Mov BasePort, DX + +CheckWSSOK: ; Check for IRQ + Add DX, 4 + + Mov AL, CODEC_INDEX_RDC + Out DX, AL + Inc DX + In AL, DX + Mov AH, AL + Dec DX + + Mov AL, CODEC_INDEX_LDC + Out DX, AL + Inc DX + In AL, DX + And AX, 3F3Fh + Neg AL + Neg AH + Add AL, 3Fh + Add AH, 3Fh + Mov [Word Ptr VolumeTable], AX + + Mov DX, CS4237Port + Test DX, DX + JZ DetectNoCS4237Port + + Add DX, 3 + + Mov AL, 3 + Out DX, AL + Inc DX + Mov AL, 0A0h + Out DX, AL + Dec DX ; Enable 3D stuff + + Mov AL, 2 + Out DX, AL + Inc DX + In AL, DX + Out DX, AL + Not AL + Mov AH, AL + And AL, 0Fh + ShR AH, 4 + + Mov [Word Ptr VolumeTable+31], AX + +DetectNoCS4237Port: + Mov EAX, 'Jeff' + ClC + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include mmxmsam.inc +include fourier.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WSSIRQHandler + + PushAD + Push DS + Push ES + + ClD + + Mov AX, CS + Mov DS, AX + Assume DS:Driver + + FNSave [FPSave] + + Mov DX, [BasePort] + Add DX, 6 + In AL, DX + Test AL, 1 + JZ WSSAckIRQ2 + + Xor AL, AL + Out DX, AL + +WSSAckIRQ2: + Mov AL, 20h + Cmp IRQ, 8 + JB WSSAckIRQ1 + + Out 0A0h, AL + +WSSAckIRQ1: + Out 20h, AL + +DMAPort1 EQU $+1 + In AL, 1 + Mov BL, AL +DMAPort2 EQU $+1 + In AL, 1 + Mov BH, AL + + Xor AX, AX + + Cmp BX, DMABUFFERLENGTH/2 + JB WSSIRQHandler1 + + Mov AX, DMABUFFERLENGTH/2 + +WSSIRQHandler1: + CLD + ; OK... time to get next block + ; Check whether stereo thing is on.. + ; + LES DI, [ActualDMAPtr] + Add DI, AX + + Mov BX, DMASize ; BX = bytes required + ShR BX, 1 + ; BX = samples required + Call SaveEMSPageFrame + + Cmp MixTransferRemaining, 0 + JNE WSSIRQHandler4 + Assume DS:Nothing + +WSSIRQHandler3: + Push BX + Push CX + Push BP + Push ES + Push DI + + Call Update + Call MixSamples + Call UpdateFourierBuffer + + Pop DI + Pop ES + Pop BP + Pop CX + Pop BX + +WSSIRQHandler4: + Mov DS, MixSegment + Mov SI, MixTransferOffset + Mov DX, BX ; DX = samples to transfer + Cmp DX, MixTransferRemaining + JBE WSSIRQHandler5 + + Mov DX, MixTransferRemaining + +WSSIRQHandler5: + +include mmxtrans.inc + + Sub MixTransferRemaining, DX ; } Memory write + Sub BX, DX + JNZ WSSIRQHandler3 + + Mov MixTransferOffset, SI ; } Memory write + + Call RestoreEMSPageFrame + + FNRstor [CS:FPSave] + + Pop ES + Pop DS + PopAD + IRet + +EndP WSSIRQHandler + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Add DI, Offset IRQData + Mov BX, [CS:DI] + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset WSSIRQHandler + + XChg [ES:BX], EAX + Mov OldWSSIRQHandler, EAX + + Mov AX, IMR + And AX, [DI+2] + + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Pop ES + PopAD + + Ret + +EndP SetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Mov BX, [IRQData+DI] + + Mov EAX, OldWSSIRQHandler + Mov [ES:BX], EAX + + Pop ES + PopAD + + Ret + +EndP ResetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StopWSS + + Mov DX, BasePort + Add DX, 4 + + Mov AL, CODEC_INDEX_INTF + Out DX, AL + Inc DX + In AL, DX + And AL, Not INTF_PEN + Out DX, AL + + Inc DX + In AL, DX + Xor AL, AL + Out DX, AL + + Dec DX + Dec DX + + Mov AL, CODEC_INDEX_PIN + Out DX, AL + Inc DX + Xor AL, AL + Out DX, AL + + Ret + +EndP StopWSS + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StartWSS + + PushA + Push ES + Push DS + + Push CS + Pop DS + Assume DS:Driver + + ; Setup DMA + Mov BX, MixSegment + Mov AX, 80 + Mov DX, DMA + Mov DI, DMABUFFERLENGTH + Call SetDMA + + LES DI, ActualDMAPtr + Xor AX, AX + Mov CX, DMABUFFERLENGTH/2 + Rep StosW + + Mov MixTransferRemaining, 0 + + Mov DX, BasePort + Call PingWSS + + Add DX, 4 + + Mov AL, CODEC_INDEX_PIN + Out DX, AL + Inc DX + Mov AL, PIN_IEN + Out DX, AL + Dec DX + + Mov AH, WSSMixConst ; Set format/frequency + Cmp Stereo, 0 + JE StartWSS1 + + Or AH, CDF_STEREO + +StartWSS1: + Mov AL, CODEC_MCE or CODEC_INDEX_CDF + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Call WaitCodec + + Mov AL, CODEC_INDEX_CDF + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Call WaitAutoCalibration + + ; Start playback + Mov AL, CODEC_INDEX_LWR_COUNT + Out DX, AL + Inc DX + + Mov AX, DMASize + ShR AX, 1 + + Cmp Stereo, 0 + JE StartWSS2 + + ShR AX, 1 + +StartWSS2: + Dec AX + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_UPR_COUNT + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_INTF + Out DX, AL + Inc DX + In AL, DX + Or AL, INTF_PEN + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_LDC + Out DX, AL + Inc DX + In AL, DX + And AL, Not LDC_LDM + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_RDC + Out DX, AL + Inc DX + In AL, DX + And AL, Not RDC_RDM + Out DX, AL + Dec DX + + Pop DS + Pop ES + PopA + + Ret + +EndP StartWSS + Assume DS:Nothing + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov SI, Offset RelocationTable + +RelocationFix: + LodsW + Test AX, AX + JZ RelocationEnd + Mov BX, AX + Mov [BX], DS + Jmp RelocationFix + + +RelocationEnd: + Call GetEMSPageFrame + Mov EMSPageFrame, AX + + In AL, 0A1h + Mov AH, AL + In AL, 21h + Mov IMR, AX + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + Call GetWSSMixConst + + Mov AX, 2643 + Mul MixSpeed + Add AX, 0FFFFh + AdC DX, 5 + (DMABUFFERLENGTH*2)/16 + FOURIERBUFFERLENGTH/8 + Mov BX, DX + + ; Allocate MixSegment first + Mov AH, 48h + + Int 21h + JNC InitSound1 + +InitSoundNoMemory: + Mov SI, Offset WSSNoMemoryMsg + Ret + +InitSound1: + Mov MixSegment, AX + Add AX, DX + Sub AX, FOURIERBUFFERLENGTH/8 + Mov FourierSegment, AX + + Call SetIRQ + Call GetTempo + Call SetTempo + + Mov DI, 1 + Call SetSAM9407 + + Mov SI, Offset WSSMsg + + Mov AX, BasePort + Mov BX, IRQ + Mov CX, DMA + + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Call ResetUART + Call ResetIRQ + Call SetIRQ + + Mov SI, Offset ReInitMsg + Mov BX, 40 + Call SetInfoLine + + Mov AL, Stereo + Call SetStereo + + Pop ES + Pop DS + PopA + + Ret + +EndP ReInitSound + Assume DS:Nothing + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, IMR + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Mov AX, MixSegment + Test AX, AX + JZ UnInitSound1 + + Mov ES, AX + Mov AH, 49h ; Release MixSegment + Int 21h + + Call ResetUART + Call StopWSS + Call ResetIRQ + +UnInitSound1: + Call GotoHomeDirectory + + ; Now to save config into driver file. + Mov AX, 3D02h ; Read write access + Mov DX, Offset DriverName + Int 21h + JC SetMixMode1 + + Mov BX, AX + + Mov AX, 4200h + Xor CX, CX + Mov DX, Offset CONFIGURATIONOFFSET + Int 21h + JC SetMixMode2 + + Mov AH, 40h + Mov CX, CONFIGSIZE + Mov DX, Offset MixMode + Int 21h + +SetMixMode2: + Mov AH, 3Eh + Int 21h + +SetMixMode1: + Ret + +EndP UnInitSound + Assume DS:Nothing + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + Ret + +EndP Poll + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Push AX + Push BX + Push DX + + Push BX + + Mov AX, MixSpeed + Mov BX, AX + Xor DX, DX + + ShL AX, 1 + RCL DX, 1 ; DX:AX = Mixspeed*2 + + ShR BX, 1 ; BX = Mixspeed/2 + + Add AX, BX + AdC DX, 0 ; DX:AX = Mixspeed*2.5 + + Pop BX ; BX = tempo + Div BX + + Mov BytesToMix, AX + + Pop DX + Pop BX + Pop AX + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + Mov CS:MixVolume, AX + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Jmp CS:RecalculateAllVolumes + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Mov CS:Stereo, AL + Cmp CS:MixSegment, 0 + JE SetStereo1 + + Push AX + + Call ResetUART + Call StopWSS + Call StartWSS + + Pop DI + And DI, 1 + Add DI, 31 + Call SetSAM9407 + + Mov DI, 2 +SetStereo2: + Call SetSAM9407 + Inc DI + Cmp DI, 30 + JBE SetStereo2 + +SetStereo1: + Call InitUART + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include loadsam.inc + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset WSS16ScreenList + + ClC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far + + Xor AH, AH + Mov AL, [CS:VolumeTable+DI] + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UpdateSoundcardVariables + + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov DX, BasePort + Add DX, 4 + + Mov AL, CODEC_INDEX_LDC + Out DX, AL + Inc DX + Mov AX, 3F3Fh + Sub AX, [Word Ptr VolumeTable] + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_RDC + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + + Mov DX, CS4237Port + Test DX, DX + JZ UpdateSoundCardVariables1 + + Add DX, 3 + + Mov AL, 3 + Out DX, AL + Inc DX + Mov AL, 0A0h + Out DX, AL + Dec DX + + Mov AL, 2 + Out DX, AL + + Mov AX, [Word Ptr VolumeTable+31] + ShL AH, 4 + Inc DX + Or AL, AH + Not AL + Out DX, AL + +UpdateSoundCardVariables1: + + Pop DS + PopA + + Ret + +EndP UpdateSoundcardVariables + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far + + Mov [CS:VolumeTable+DI], AL + Cmp DI, 31 + JAE SetVariable1 + Cmp DI, 2 + JB SetVariable1 + + Call SetSAM9407 + Ret + +SetVariable1: + Call UpdateSoundcardVariables + Ret + +EndP SetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetUART + + Mov DX, CS:SAM9407Port + Test DX, DX + JZ ResetUART1 + + Inc DX + + Mov AL, 0FFh + Out DX, AL + +ResetUART1: + Ret + +EndP ResetUART + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitUART + + ClI + + Mov DX, CS:SAM9407Port + Inc DX + Mov AL, 0FFh ; reset + Out DX, AL + + Xor CX, CX + +DetectUARTPause: + In AL, 21h + In AL, 0A1h + Loop DetectUARTPause + + Mov AL, 0FFh + Out DX, AL + + Xor CX, CX + +DetectUART1: + In AL, DX + Test AL, 80h + LoopNZ DetectUART1 + JNZ DetectUARTFailed + + Dec DX + In AL, DX + Inc DX + Cmp AL, 0FEh + JNE DetectUART1 + + Xor CX, CX + +DetectUART3: + In AL, DX + Test AL, 40h + LoopNZ DetectUART3 + JNZ DetectUARTFailed + + Mov AL, 03Fh + Out DX, AL + + Xor CX, CX + +DetectUART2: + In AL, DX + Test AL, 80h + LoopNZ DetectUART2 + JNZ DetectUARTFailed + + Dec DX + In AL, DX + Inc DX + Cmp AL, 0FEh + JNE DetectUART2 + Dec DX + + Mov AL, 0FFh + Out DX, AL + + DB 85h +DetectUARTFailed: + StC + StI + Ret + +EndP InitUART + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UARTOut + + Push CX + Push DX + Mov DX, CS:SAM9407Port + + Push AX + Xor CX, CX + Inc DX + +UARTOut1: + In AL, DX + Test AL, 40h + LoopNZ UARTOut1 + + Pop AX + JNZ UARTOutEnd + + Dec DX + Out DX, AL + +UARTOutEnd: + Pop DX + Pop CX + + Ret + +EndP UARTOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +InterpretState DB 0 +InterpretType DB 0 + +Proc SendUARTOut Far ; Local interpreter activated with 0F0h 0F0h. + + Mov AH, CS:InterpretState + Cmp AH, 2 + JB SendUARTOut1 + +; In interpreter. + JE SendUARTOut3 + +; Have InterpretType, now get parameter, then return to normal. + + Cmp AL, 7Fh + JA SendUARTOut4 + + Push BX + + Mov BL, CS:InterpretType ; Want BX = InterpretType*64+Channel + ; + ShL BX, 6 + Add BL, [DI+20h] + And BX, 127 + Mov [CS:FilterParameters+BX], AL + + Pop BX + + Test SI, SI + JZ SendUARTOut4 + + Or Byte Ptr [SI], 64 + +SendUARTOut4: + Mov CS:InterpretState, 0 + Ret + +SendUARTOut3: + Cmp AL, 2 + JAE SendUARTOut4 + + Mov CS:InterpretType, AL + Jmp SendUARTOutStateInc + +SendUARTOut1: + Cmp AL, 0F0h + JNE SendUARTOut2 + +SendUARTOutStateInc: + Inc CS:InterpretState + Ret + +SendUARTOut2: + Test AH, AH + JZ SendUARTOutEnd + + Push AX + Mov AL, 0F0h + Call UARTOut + Pop AX + Mov CS:InterpretState, 0 + +SendUARTOutEnd: + Cmp AL, 0FCh + JE ResetFilters + Cmp AL, 0FAh + JE ResetFilters + + Cmp AL, 0FFh + JNE SendUARTOutNoClear + +ResetFilters: + PushA + Push ES + + Push CS + Pop ES + + Mov DI, Offset FilterParameters + Mov CX, 64 + Mov AL, 7Fh + Rep StosB + Mov CX, 64 + Xor AX, AX + Rep StosB + + Pop ES + PopA + +SendUARTOutNoClear: + Call UARTOut + Ret + +EndP SendUARTOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetWaveForm Far ; Given ES:DI = destination + Assume DS:Nothing ; want 2048 samples. + + PushA + Push DS + + Mov DS, FourierSegment + Mov SI, FourierBufferStart + Mov CX, 2048 + +GetWaveForm1: + MovsW + And SI, (FOURIERBUFFERLENGTH*2)-1 + Dec CX + JNZ GetWaveForm1 + + Pop DS + PopA + + Ret + +EndP GetWaveForm + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. + +StopAfterPlay DW 0 +DefaultChannels DW 128 +DriverFlags DW 7 + DW 4 Dup (0) + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + + DW Offset SendUARTOut + DW Offset GetWaveForm + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/ST97CODE.ASM b/SoundDrivers/ST97CODE.ASM new file mode 100755 index 0000000..7e9d21a --- /dev/null +++ b/SoundDrivers/ST97CODE.ASM @@ -0,0 +1,3171 @@ +; +; ST 97/42 PCI Codec +; + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc +include mmx.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;********************************** + +STEREOENABLED EQU 1 +DMABUFFERLENGTH EQU 8192 +MIXRESOLUTION EQU 32 ; 32 bit mixing for +MIXTABLESIZE EQU 2*256*65 +DATAFLAG EQU 200h +ACKFLAG EQU 300h + +PNPVENDORID EQU 3746630Eh + +DMASize DW DMABUFFERLENGTH / 2 + +WSSMsg DB "Sound Track Codec", 13 + DB "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, DMA ", 0FDh, "D", 0 + +WSSNoMemoryMsg DB "Sound Track Codec", 13 + DB "Error: Insufficient memory", 0 + +ReinitMsg DB "Sound Track Codec reinitialised", 0 + +ConfigErrorMsg DB "Error saving configuration to ITSTCODE.DRV", 0 +ConfigOKMsg DB "Configuration saved to ITSTCODE.DRV", 0 + +DriverName DB "ITSTCODE.DRV", 0 + +Forced DB 0 +Stereo DB 0 +WSSMixConst DB 0 + +ALIGN 2 + +MixVolume DW 0 + +BytesToMix DW 1000 + +MixSegment DW 0 +DMASegment DW 0 + +MixTransferOffset DW 0 +MixTransferRemaining DW 0 + +CONFIGURATIONOFFSET EQU $+128 +CONFIGSIZE EQU 37 +MixMode DW 0 +MixModeOffset DW 0 +Filter DW 0 +VolumeTable DB 56, 56 + DB 60h, 60h, 0Ch ; Low Band + DB 40h, 40h, 1Bh ; Med Low Band + DB 40h, 40h, 72h ; Med High Band + DB 60h, 60h, 40h ; High Band + DB 0, 0, 0 ; Echo + DB 0, 2 ; Surround + DB 0, 90h, 4, 7Fh, 22h ; Reverb + DB 0, 90h, 2, 40h, 9, 3, 13h ; Chorus + DB 0, 0 ; SRS stuff. + +ALIGN 2 + +IMR DW 0 +OldWSSIRQHandler DD 0 + +SAM9407Reset DW 66 + DW 1BEh, 16Fh, 7Fh, 7Fh, ACKFLAG ; Audio in on + DW 1BEh, 168h, 7Fh, 7Fh, ACKFLAG ; Echo on + DW 1BEh, 16Ch, 7Fh, 7Fh, ACKFLAG ; Reverb on + DW 1BEh, 16Dh, 7Fh, 7Fh, ACKFLAG ; Chorus on + DW 1BEh, 16Bh, 0, 0, ACKFLAG ; Equalizer type + DW 1BEh, 16Eh, 7Fh, 7Fh, ACKFLAG ; Surround on + DW 1BEh, 165h, 7Fh, 7Fh ; Post eff on Audio in + DW 1BEh, 166h, 7Fh, 7Fh ; Post eff on reverb, chorus + DW 1BEh, 133h, 0, 0 ; 2 Speaker + DW 1BEh, 120h, 7Fh, 7Fh ; Stereo input 2 + DW 1BEh, 134h, 0FFh, 0FFh ; Left gain + DW 1BEh, 135h, 0FFh, 0FFh ; Right gain + DW 1BEh, 136h, 0, 0 ; Left pan + DW 1BEh, 137h, 7Fh, 7Fh ; Right pan + DW 1BEh, 107h, 0FFh, 0FFh ; Master volume + +SAM9407EqLBL DW 4 + DW 1BEh, 110h, DATAFLAG, 60h +SAM9407EqLBR DW 4 + DW 1BEh, 114h, DATAFLAG, 60h +SAM9407EqLBF DW 4 + DW 1BEh, 118h, DATAFLAG, 0Ch +SAM9407EqMLBL DW 4 + DW 1BEh, 111h, DATAFLAG, 40h +SAM9407EqMLBR DW 4 + DW 1BEh, 115h, DATAFLAG, 40h +SAM9407EqMLBF DW 4 + DW 1BEh, 119h, DATAFLAG, 1Bh +SAM9407EqMHBL DW 4 + DW 1BEh, 112h, DATAFLAG, 40h +SAM9407EqMHBR DW 4 + DW 1BEh, 116h, DATAFLAG, 40h +SAM9407EqMHBF DW 4 + DW 1BEh, 11Ah, DATAFLAG, 72h +SAM9407EqHBL DW 4 + DW 1BEh, 113h, DATAFLAG, 60h +SAM9407EqHBR DW 4 + DW 1BEh, 117h, DATAFLAG, 60h +SAM9407EqHBF DW 4 + DW 1BEh, 11Bh, DATAFLAG, 0Ch +SAM9407EchoLevel DW 4 + DW 1BEh, 128h, DATAFLAG, 0 +SAM9407EchoTime DW 4 + DW 1BEh, 129h, DATAFLAG, 2Bh +SAM9407EchoFeed DW 4 + DW 1BEh, 12Ah, DATAFLAG, 40h +SAM9407SurroundVolume DW 4 + DW 1BEh, 130h, DATAFLAG, 0 +SAM9407SurroundDelay DW 4 + DW 1BEh, 131h, DATAFLAG, 2 +SAM9407ReverbSend DW 4 + DW 1BEh, 127h, DATAFLAG, 0 +SAM9407ReverbVolume DW 3 + DW 1BEh, 13Ah, DATAFLAG +SAM9407ReverbType DW 4 + DW 1BEh, 169h, DATAFLAG, 4 +SAM9407ReverbTime DW 3 + DW 1BEh, 178h, DATAFLAG +SAM9407ReverbFeedback DW 3 + DW 1BEh, 179h, DATAFLAG +SAM9407ChorusSend DW 4 + DW 1BEh, 124h, DATAFLAG, 0 +SAM9407ChorusVolume DW 3 + DW 1BEh, 13Bh, DATAFLAG +SAM9407ChorusType DW 4 + DW 1BEh, 16Ah, DATAFLAG, 2 +SAM9407ChorusDelay DW 3 + DW 1BEh, 174h, DATAFLAG +SAM9407ChorusFeedback DW 3 + DW 1BEh, 175h, DATAFLAG +SAM9407ChorusRate DW 3 + DW 1BEh, 176h, DATAFLAG +SAM9407ChorusDepth DW 3 + DW 1BEh, 177h, DATAFLAG +SAM9407Mono DW 4 + DW 1BEh, 132h, 7Fh, 0 +SAM9407Stereo DW 4 + DW 1BEh, 132h, 0, 0 + +SAM9407Strings DW Offset SAM9407Reset ;1 + DW Offset SAM9407EqLBL, Offset SAM9407EqLBR + DW Offset SAM9407EqLBF + DW Offset SAM9407EqMLBL, Offset SAM9407EqMLBR + DW Offset SAM9407EqMLBF + DW Offset SAM9407EqMHBL, Offset SAM9407EqMHBR + DW Offset SAM9407EqMHBF + DW Offset SAM9407EqHBL, Offset SAM9407EqHBR + DW Offset SAM9407EqHBF + DW Offset SAM9407EchoLevel ; 14 + DW Offset SAM9407EchoTime + DW Offset SAM9407EchoFeed + DW Offset SAM9407SurroundVolume ; 17 + DW Offset SAM9407SurroundDelay + DW Offset SAM9407ReverbSend ; 19 + DW Offset SAM9407ReverbVolume + DW Offset SAM9407ReverbType + DW Offset SAM9407ReverbTime + DW Offset SAM9407ReverbFeedback ; 23 + DW Offset SAM9407ChorusSend ; 24 + DW Offset SAM9407ChorusVolume + DW Offset SAM9407ChorusType + DW Offset SAM9407ChorusDelay + DW Offset SAM9407ChorusFeedback + DW Offset SAM9407ChorusRate + DW Offset SAM9407ChorusDepth ; 30 + DW Offset SAM9407Mono ; 31 + DW Offset SAM9407Stereo +FilterValue DD 0 +FilterValue2 DD 0 + +MixSpeedTable DW 5513, 41h + DW 6615, 4Fh + DW 8000, 40h + DW 9600, 4Eh + DW 11025, 43h + DW 16000, 42h + DW 18900, 45h + DW 22050, 47h + DW 27429, 44h + DW 32000, 46h + DW 33075, 4Dh + DW 37800, 49h + DW 44100, 4Bh + DW 48000, 4Ch + DW 54860, 48h + DW 64000, 4Ah + +IRQData Label Word + DW 20h, 1111111111111110b ; IRQ 0 + DW 24h, 1111111111111101b ; IRQ 1 + DW 28h, 1111110111111011b ; IRQ 2 + DW 2Ch, 1111111111110111b ; IRQ 3 + DW 30h, 1111111111101111b ; IRQ 4 + DW 34h, 1111111111011111b ; IRQ 5 + DW 38h, 1111111110111111b ; IRQ 6 + DW 3Ch, 1111111101111111b ; IRQ 7 + DW 1C0h, 1111111011111011b ; IRQ 8 + DW 1C4h, 1111110111111011b ; IRQ 9 + DW 1C8h, 1111101111111011b ; IRQ 10 + DW 1CCh, 1111011111111011b ; IRQ 11 + DW 1D0h, 1110111111111011b ; IRQ 12 + DW 1D4h, 1101111111111011b ; IRQ 13 + DW 1D8h, 1011111111111011b ; IRQ 14 + DW 1DCh, 0111111111111011b ; IRQ 15 + +;********************************** +; WSS Registers +;********************************** + +CODEC_INDEX_LIC = 00 +CODEC_INDEX_RIC = 01h +CODEC_INDEX_LX1C = 02h +CODEC_INDEX_RX1C = 03h +CODEC_INDEX_LX2C = 04h +CODEC_INDEX_RX2C = 05h +CODEC_INDEX_LDC = 06h +CODEC_INDEX_RDC = 07h +CODEC_INDEX_CDF = 08h +CODEC_INDEX_INTF = 09h +CODEC_INDEX_PIN = 0Ah +CODEC_INDEX_TEST = 0Bh +CODEC_INDEX_MISC = 0Ch +CODEC_INDEX_DIGMIX = 0Dh +CODEC_INDEX_UPR_COUNT = 0Eh +CODEC_INDEX_LWR_COUNT = 0Fh + +CODEC_MCE = 40h + +LDC_LDM = 80h +LDC_LDA = 3Fh + +RDC_RDM = 80h +RDC_RDA = 3Fh + +CDF_STEREO = 10h + +INTF_PEN = 01h +INTF_CEN = 02h +INTF_SDC = 04h +INTF_ACAL = 08h +INTF_PPIO = 40h +INTF_CPIO = 80h + +PIN_IEN = 2 + +TEST_ORL = 03h +TEST_ORR = 0Ch +TEST_DRS = 10h +TEST_ACI = 20h +TEST_PUR = 40h +TEST_COR = 80h + +;********************************** + +WSS16ScreenList Label + DW 16 + DW Near Ptr IdleFunctionList + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr WSSHeaderLine + + DW Near Ptr DriverText + + DW Near Ptr MixModeText + DW Near Ptr MixModeButton1 ; 6 + DW Near Ptr MixModeButton2 ; + DW Near Ptr MixModeButton3 ; 8 + DW Near Ptr MixModeButton4 ; 9 + + DW Near Ptr FilterText + DW Near Ptr FilterButton1 ; 11 + DW Near Ptr FilterButton2 + DW Near Ptr FilterButton3 + + DW Near Ptr VolumeText + DW Near Ptr VolumeBox1 + + DW Near Ptr MasterVolumeLeft ; 16 + DW Near Ptr MasterVolumeRight ; 17 + + DW Near Ptr CS4237SRSCenter ; 18 + DW Near Ptr CS4237SRSSpace ; 19 + DW Near Ptr CSControlPortText + +ST42A DW Near Ptr SAM9407PortText ; 21 + DW Near Ptr SAM9407ParametersText + DW Near Ptr SAM9407ParametersBox + + DW Near Ptr EqLBL ; 24 + DW Near Ptr EqLBR + DW Near Ptr EqLBF + + DW Near Ptr EqMLBL + DW Near Ptr EqMLBR + DW Near Ptr EqMLBF + + DW Near Ptr EqMHBL + DW Near Ptr EqMHBR + DW Near Ptr EqMHBF + + DW Near Ptr EqHBL + DW Near Ptr EqHBR + DW Near Ptr EqHBF + + DW Near Ptr EchoLevel ; 33 + DW Near Ptr EchoTime + DW Near Ptr EchoFeedback + + DW Near Ptr SurroundVolume + DW Near Ptr SurroundDelay + + DW Near Ptr ReverbSend ; 38 + DW Near Ptr ReverbVolume + DW Near Ptr ReverbType + DW Near Ptr ReverbTime + DW Near Ptr ReverbFeedback + + DW Near Ptr ChorusSend + DW Near Ptr ChorusVolume + DW Near Ptr ChorusType + DW Near Ptr ChorusDelay + DW Near Ptr ChorusFeedback + DW Near Ptr ChorusRate + DW Near Ptr ChorusDepth + + + DW 0 + +WSSHeaderLine DW 10 + DB "Sound Track Codec Driver", 0 + +EmptyObject DW 1 + DB 0, 0 + DB 0 + DB 0 + +DriverText DW 1 + DB 28, 48 + DB 21h + DB "Sound Track Codec Driver 1.0 for Impulse Tracker", 0 + +CSControlPortText DW 1 + DB 28, 47 + DB 21h + DB "Sound Track CS4237 Control Port ", 0FDh, "Xh", 0 +CS4237Port DW 0 + +SAM9407PortText DW 1 + DB 28, 46 + DB 21h + DB "Sound Track SAM9407 Port ", 0FDh, "Xh", 0 +SAM9407Port DW 0 + +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +IdleFunctionList DD 0 + DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +VolumeText DW 1 + DB 2, 14 + DB 20h + DB "Master Volume Left", 13 + DB "Master Volume Right", 13 + DB "CS4237 SRS Center", 13 + DB "CS4237 SRS Space" + DB 0 + +VolumeBox1 DW 0 + DB 21, 13, 31, 18 + DB 25 + +MasterVolumeLeft DW 14 + DB 22, 14 + DW 0, 63 + DW 9, 0 + DW 0FFFFh, 17, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 8 + +MasterVolumeRight DW 14 + DB 22, 15 + DW 0, 63 + DW 9, 1 + DW 16, 18, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 8 + +CS4237SRSCenter DW 14 + DB 22, 16 + DW 0, 15 + DW 9, 31 + DW 17, 19, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 8 + +CS4237SRSSpace DW 14 + DB 22, 17 + DW 0, 15 + DW 9, 32 + DW 18, 6, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 8 + +MixModeText DW 1 + DB 2, 19 + DB 20h + DB "Mixing Rate: ", 0FDh, "D, Mode:", 0 +MixSpeed DW 48000 + +MixModeButton1 DW 2 + DW 19, 7, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment1 DW 0 + DW 0 + DW Offset SetMixMode +DriverSegment2 DW 0 + DB 3, 21, 32, 23, 8 + DB 0 + DB " 16 Bit, Non-Interpolated", 0 + +MixModeButton2 DW 2 + DW 6, 8, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment3 DW 0 + DW 2 + DW Offset SetMixMode +DriverSegment4 DW 0 + DB 3, 24, 32, 26, 8 + DB 0 + DB " 16 Bit, Interpolated", 0 + +MixModeButton3 DW 2 + DW 7, 9, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment5 DW 0 + DW 4 + DW Offset SetMixMode +DriverSegment6 DW 0 + DB 3, 27, 32, 29, 8 + DB 0 + DB " 32 Bit, Interpolated", 0 + +MixModeButton4 DW 2 + DW 8, 11, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment7 DW 0 + DW 6 + DW Offset SetMixMode +DriverSegment8 DW 0 + DB 3, 30, 32, 32, 8 + DB 0 + DB " 32 Bit, Ultra Quality", 0 + +FilterText DW 1 + DB 2, 34 + DB 20h + DB "Filter mode", 0 + +FilterButton1 DW 2 + DW 9, 12, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment9 DW 0 + DW 0 + DW Offset SetFilter +DriverSegment10 DW 0 + DB 3, 36, 29, 38, 8 + DB 0 + DB " No Filter", 0 + +FilterButton2 DW 2 + DW 11, 13, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment11 DW 0 + DW 1 + DW Offset SetFilter +DriverSegment12 DW 0 + DB 3, 39, 29, 41, 8 + DB 0 + DB " 50% Filter", 0 + +FilterButton3 DW 2 + DW 12 +ST42B DW 24, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment13 DW 0 + DW 2 + DW Offset SetFilter +DriverSegment14 DW 0 + DB 3, 42, 29, 44, 8 + DB 0 + DB " 75% Filter", 0 + +SAM9407ParametersText DW 1 + DB 36, 14 + DB 20h + DB "Low Band Left", 13 + DB "Low Band Right", 13 + DB "Low Band Frequency", 13 + DB "Med Low Band Left", 13 + DB "Med Low Band Right", 13 + DB "Med Low Band Frequency", 13 + DB "Med High Band Left", 13 + DB "Med High Band Right", 13 + DB "Med High Band Frequency", 13 + DB "High Band Left", 13 + DB "High Band Right", 13 + DB "High Band Frequency", 13 + DB "Echo Level", 13 + DB "Echo Time", 13 + DB "Echo Feedback", 13 + DB "Surround Volume", 13 + DB "Surround Delay", 13 + DB "Reverb Send", 13 + DB "Reverb Volume", 13 + DB "Reverb Type", 13 + DB "Reverb Time", 13 + DB "Reverb Feedback", 13 + DB "Chorus Send", 13 + DB "Chorus Volume", 13 + DB "Chorus Type", 13 + DB "Chorus Delay", 13 + DB "Chorus Feedback", 13 + DB "Chorus Rate", 13 + DB "Chorus Depth", 13 + DB 0 + +EqLBL DW 14 + DB 60, 14 + DW 0, 127 + DW 9, 2 + DW 13, 25, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqLBR DW 14 + DB 60, 15 + DW 0, 127 + DW 9, 3 + DW 24, 26, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqLBF DW 14 + DB 60, 16 + DW 0, 127 + DW 9, 4 + DW 25, 27, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqMLBL DW 14 + DB 60, 17 + DW 0, 127 + DW 9, 5 + DW 26, 28, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqMLBR DW 14 + DB 60, 18 + DW 0, 127 + DW 9, 6 + DW 27, 29, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqMLBF DW 14 + DB 60, 19 + DW 0, 127 + DW 9, 7 + DW 28, 30, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqMHBL DW 14 + DB 60, 20 + DW 0, 127 + DW 9, 8 + DW 29, 31, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqMHBR DW 14 + DB 60, 21 + DW 0, 127 + DW 9, 9 + DW 30, 32, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqMHBF DW 14 + DB 60, 22 + DW 0, 127 + DW 9, 10 + DW 31, 33, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqHBL DW 14 + DB 60, 23 + DW 0, 127 + DW 9, 11 + DW 32, 34, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqHBR DW 14 + DB 60, 24 + DW 0, 127 + DW 9, 12 + DW 33, 35, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqHBF DW 14 + DB 60, 25 + DW 0, 127 + DW 9, 13 + DW 34, 36, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EchoLevel DW 14 + DB 60, 26 + DW 0, 127 + DW 9, 15 + DW 35, 37, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EchoTime DW 14 + DB 60, 27 + DW 0, 127 + DW 9, 14 + DW 36, 38, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EchoFeedback DW 14 + DB 60, 28 + DW 0, 127 + DW 9, 16 + DW 37, 39, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +SurroundVolume DW 14 + DB 60, 29 + DW 0, 255 + DW 9, 17 + DW 38, 40, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +SurroundDelay DW 14 + DB 60, 30 + DW 0, 127 + DW 9, 18 + DW 39, 41, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ReverbSend DW 14 + DB 60, 31 + DW 0, 127 + DW 9, 19 + DW 40, 42, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ReverbVolume DW 14 + DB 60, 32 + DW 0, 255 + DW 9, 20 + DW 41, 43, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + + +ReverbType DW 14 + DB 60, 33 + DW 0, 7 + DW 9, 21 + DW 42, 44, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ReverbTime DW 14 + DB 60, 34 + DW 0, 127 + DW 9, 22 + DW 43, 45, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ReverbFeedback DW 14 + DB 60, 35 + DW 0, 127 + DW 9, 23 + DW 44, 46, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ChorusSend DW 14 + DB 60, 36 + DW 0, 127 + DW 9, 24 + DW 45, 47, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ChorusVolume DW 14 + DB 60, 37 + DW 0, 255 + DW 9, 25 + DW 46, 48, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ChorusType DW 14 + DB 60, 38 + DW 0, 7 + DW 9, 26 + DW 47, 49, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ChorusDelay DW 14 + DB 60, 39 + DW 0, 127 + DW 9, 27 + DW 48, 50, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ChorusFeedback DW 14 + DB 60, 40 + DW 0, 127 + DW 9, 28 + DW 49, 51, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ChorusRate DW 14 + DB 60, 41 + DW 0, 127 + DW 9, 29 + DW 50, 52, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ChorusDepth DW 14 + DB 60, 42 + DW 0, 127 + DW 9, 30 + DW 51, 0FFFFh, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +SAM9407ParametersBox DW 0 + DB 59, 13, 75, 43 + DB 25 + +; OldIRQData DD 0 +; OldIRQOffset DD 0 +; UseOldIRQ DB 0 + +; ÄÄ MixingRoutines ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + + +include dmasirq.inc +include mix.inc + +include m12bit.mix +include m12biti.mix +include m32biti.mix +include m32ultra.mix + +MixFunctionTables Label + +include m12bit.inc ; contains the tables +include m12biti.inc +include m32biti.inc +include m32ultra.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +RelocationTable Label Word + DW Offset DriverSegment1, Offset DriverSegment2 + DW Offset DriverSegment3, Offset DriverSegment4 + DW Offset DriverSegment5, Offset DriverSegment6 + DW Offset DriverSegment7, Offset DriverSegment8 + DW Offset DriverSegment9, Offset DriverSegment10 + DW Offset DriverSegment11, Offset DriverSegment12 + DW Offset DriverSegment13, Offset DriverSegment14 + DW 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixMode Far + + Push CS + Pop ES + Mov DI, Offset MixMode + + Ret + +EndP GetMixMode + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetFilter Far + + Push CS + Pop ES + Mov DI, Offset Filter + + Ret + +EndP GetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetFilter Far + + Mov AX, [SI+22] + Mov CS:FilterValue, 0 + Mov CS:Filter, AX + + Mov AX, 1 + Ret + +EndP SetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WaitCoDec + + Push CX + + Mov CX, 0F000h + +WaitCoDec1: + In AL, DX + Test AL, AL + JNS WaitCoDec2 + Loop WaitCoDec1 + + StC + +WaitCoDec2: + Pop CX + Ret + +EndP WaitCoDec + +; ÄÄ SAM9407InByte ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SAM9407InByte ; Returns AL + + Push DX + Mov DX, CS:SAM9407Port + Inc DX + +SAM9407InByte1: + In AL, DX + Test AL, AL + JS SAM9407InByte1 + + Dec DX + In AL, DX + Pop DX + + Ret + +EndP SAM9407InByte + +; ÄÄ ST97SendByte ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SAM9407SendByte ; DX = port, AL = data + + Push AX + Push DX + Mov DX, CS:SAM9407Port + Inc DX + +SAM9407SendByte1: + In AL, DX + Test AL, 40h + JNZ SAM9407SendByte1 + + Pop DX + Pop AX + + Out DX, AL + + Ret + +EndP SAM9407SendByte + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetSAM9407 ; DI = index. 1 = full reinit. + + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + LEA SI, [SAM9407Strings+EDI+EDI-2] + Mov SI, [SI] + + LodsW + Mov CX, AX + +SetSAM9407_1: +; AH = 0 = normal data, 1 = command, 2 = param, 3 = ack. + + Mov DX, SAM9407Port + Test DX, DX + JZ NoSAM9407 + + LodsW + + Cmp AH, 2 + JB SetSAM9407_3 + JA SetSAM9407_4 + + Mov AL, [VolumeTable+DI] + Jmp SetSAM9407_2 + +SetSAM9407_4: + Call SAM9407InByte + Test AL, AL + JNZ SetSAM9407_4 + Jmp SetSAM9407_5 + +SetSAM9407_3: + And AH, 1 + Add DL, AH + +SetSAM9407_2: + Call SAM9407SendByte + +SetSAM9407_5: + Dec CX + JNZ SetSAM9407_1 + +NoSAM9407: + Pop DS + PopA + + Ret + +EndP SetSAM9407 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WaitAutoCalibration + + Push CX + Mov CX, 0F000h + +WaitAutoCalibration1: + Mov AL, CODEC_INDEX_TEST + Out DX, AL + Inc DX + In AL, DX + Dec DX + Test AL, TEST_ACI + JNZ WaitAutoCalibration2 + Loop WaitAutoCalibration1 + + StC + +WaitAutoCalibration2: + Pop CX + Ret + +EndP WaitAutoCalibration + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixMode Far + + Mov AX, [SI+22] + + ClI + + Mov CS:MixMode, AX + + Mov BX, 180 + Mul BX + Mov CS:MixModeOffset, AX + + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS:RecalculateAllVolumes + + StI + Mov AX, 1 + Ret + +EndP SetMixMode + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetWSSMixConst ; Work out value.. and nearest + ; mixspeed value. + + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, CmdLineMixSpeed + Mov CX, MixSpeed + Test AX, AX + JZ GetWSSMixConst1 + + Mov CX, 64000 + Cmp AX, CX + JA GetWSSMixConst1 + + Mov CX, 8000 + Cmp AX, CX + JB GetWSSMixConst1 + + Mov CX, AX + +GetWSSMixConst1: ; CX = desired mixspeed + Mov SI, Offset MixSpeedTable + Mov DX, 16 ; 16 different available speeds + + Xor BX, BX + +GetWSSMixConst2: + LodsW + Cmp AX, BX + JB GetWSSMixConst3 + Cmp AX, CX + JA GetWSSMixConst3 + + Mov BX, AX + Mov DH, [SI] + +GetWSSMixConst3: + LodsW ; Add SI, 2 + Dec DL + JNZ GetWSSMixConst2 + + Mov MixSpeed, BX + Mov WSSMixConst, DH + + Pop DS + PopA + Ret + +EndP GetWSSMixConst + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PingWSS ; Check BasePort, DX = BasePort + ; Preserves DX, destroys AX + + Push DX + + Add DX, 6 + + + In AL, DX + Xor AL, AL + Out DX, AL + + Dec DX + Dec DX + Call WaitCodec + JC PingWSSFailure + + In AL, DX + Test AL, AL + JS PingWSSFailure + + Mov AL, CODEC_INDEX_MISC + Out DX, AL + Inc DX ; DX = Data port + In AL, DX + Mov AH, AL ; AH = Revision + + Xor AL, AL ; Write 0 revision + Out DX, AL + In AL, DX + And AX, 8F8Fh + Cmp AL, AH + JNE PingWSSFailure + Dec DX ; DX = AD1848 baseport + + Mov AL, CODEC_MCE or CODEC_INDEX_INTF + Out DX, AL + Inc DX + Mov AL, INTF_ACAL or INTF_SDC + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_INTF + Out DX, AL + Inc DX + Mov AL, INTF_ACAL or INTF_SDC + Out DX, AL + Dec DX + + Call WaitAutoCalibration ; Returns carry if error + ; Carry clear if none. + +; JC PingWSSFailure + + Pop DX + Ret + +PingWSSFailure: + Pop DX + + StC + Ret + + +EndP PingWSS + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +PnP_SerialID DD 0 +PnP_VendorID DD 0 +PnP_ReadPort DW 0 +PnP_CSN DB 0 +PnP_CardFound DB 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_Delay + Assume DS:Driver + + Push AX CX + + Mov CX, 180h +PnP_Delay1: + In AL, 21h + Loop PnP_Delay1 + + Pop CX AX + Ret + +EndP PnP_Delay + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_WriteData + + Mov DX, 279h + Out DX, AL + + Mov AL, AH + Mov DH, 0Ah + Out DX, AL + Ret + +EndP PnP_WriteData + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_ReadData + + Mov DX, 279h + Out DX, AL + + Mov DX, PnP_ReadPort + In AL, DX + + Ret + +EndP PnP_ReadData + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_Isolate + + Mov AX, 402h + Call Pnp_WriteData ; Reset CSNs + +PnP_IsolateNextCard: + Mov AX, 0003h + Call PnP_WriteData ; Wake[0] + + Mov AX, PnP_ReadPort + ShL AX, 6 + Xor AL, AL + Call PnP_WriteData ; Set Read Data port. + + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + + Mov AL, 1 ; Serial Isolation + Mov DX, 279h + Out DX, AL + + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + + Mov BL, 6Ah + Mov CX, 64 + Mov DX, PnP_ReadPort + + ClI + +PnP_Isolate1: + ShR PnP_SerialID, 1 + RCR PnP_VendorID, 1 + + Mov BH, BL + ShR BH, 1 + Xor BH, BL + ShR BX, 1 + + In AL, DX + Mov AH, AL + Call PnP_Delay + In AL, DX + Call PnP_Delay + + Cmp AX, 55AAh + JNE PnP_Isolate2 + + Xor BL, 80h + Or PnP_SerialID, 80000000h + +PnP_Isolate2: + Dec CX + JNZ PnP_Isolate1 + + Mov CX, 8 + Xor BH, BH + +PnP_Isolate3: + ShR BH, 1 + + In AL, DX + Mov AH, AL + Call PnP_Delay + In AL, DX + Call PnP_Delay + Cmp AX, 55AAh + JNE PnP_Isolate4 + + Or BH, 80h + +PnP_Isolate4: + Dec CX + JNZ PnP_Isolate3 + + StI + + Cmp BL, BH ; Matching Checksum? + JNE PnP_IsolateFinished + + ; assign CSN + Inc PnP_CSN + + Mov AL, 6 + MOv AH, PnP_CSN + Call PnP_WriteData + + Cmp PnP_VendorID, PNPVENDORID + JNE PnP_IsolateNextCard +; Cmp PnP_SerialID, PNPSERIALID +; JNE PnP_IsolateNextCard + + Mov AL, 3 + Call PnP_WriteData + + Mov AX, 007h ; Configuration device + Call PnP_WriteData + + Mov AL, 60h + Call PnP_ReadData + Mov AH, AL + Mov AL, 61h + Call PnP_ReadData ; AX = address. + + Test AX, AX + JZ PnP_IsolateNextCard + + Cmp BasePort, 0FFFFh + JE PnPBasePortOK + + Cmp BasePort, AX + JNE PnP_IsolateNextCard + +PnPBasePortOK: + Cmp AX, 534h + JNE PnPBasePortTranslate1 + + Mov AX, 530h + +PnPBasePortTranslate1: + Cmp AX, 0F44h + JNE PnPBasePortTranslate2 + + Mov AX, 0F40h + +PnPBasePortTranslate2: + Cmp AX, 608h + JNE PnPBasePortTranslate3 + + Mov AX, 604h + +PnPBasePortTranslate3: + Cmp AX, 0E84h + JNE PnPBasePortTranslate4 + + Mov AX, 0E80h + +PnPBasePortTranslate4: + Mov BasePort, AX + + Mov AL, 70h + Call PnP_ReadData ; AL[3:0] = IRQ + And AX, 15 + JZ PnP_IsolateNextCard + Mov IRQ, AX + + Mov AL, 74h + Call PnP_ReadData ; AL[2:0] = DMA + And AX, 7 + Cmp AL, 4 + JE PnP_IsolateNextCard + Mov DMA, AX + + Mov AX, 207h ; CS4237 + Call PnP_WriteData + + Mov AL, 60h + Call PnP_ReadData + Mov AH, AL + Mov AL, 61h + Call PnP_ReadData ; AX = address. + Test AX, AX + JZ PnP_IsolateNextCard + + Mov CS4237Port, AX + + Mov AX, 407h ; SAM9407 + Call PnP_WriteData + + Mov AL, 60h + Call PnP_ReadData + Mov AH, AL + Mov AL, 61h + Call PnP_ReadData ; AX = address. + Test AX, AX + JZ PnP_NoSAM9407 + + Mov SAM9407Port, AX + + Mov Pnp_CardFound, 1 + Jmp PnP_IsolateNextCard + +Pnp_NoSAM9407: + Xor AX, AX + Mov SAM9407Port, AX + Mov ST42A, AX + Dec AX + Mov ST42B, AX + Mov Pnp_CardFound, 1 + Jmp PnP_IsolateNextCard + + +PnP_IsolateFinished: + Mov AL, PnP_CSN + ShL AL, 1 + Or AL, PnP_CardFound + + Ret + +EndP PnP_Isolate + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far ; returns carry clear if succesful + + Push CS + Pop DS + + Xor AL, AL + Mov DX, 279h + Out DX, AL + Out DX, AL + + Mov AL, 6Ah ; Starting value + Mov CX, 32 + +PnP_InitiationKeyLoop: + Out DX, AL + + Mov AH, AL + ShR AH, 1 + Xor AH, AL + ShR AX, 1 + + Dec CX + JNZ PnP_InitiationKeyLoop + +; Try three ports before concluding no PnP cards: 20Fh, 27Bh, 213h + +PnP_DetectCardPort1: + Mov PnP_ReadPort, 20Fh + Call PnP_Isolate + JZ PnP_DetectCardPort2 + Test AL, 1 + JZ PnP_DetectCardNotFound + Jmp PnP_DetectCardFound + +PnP_DetectCardPort2: + Mov PnP_ReadPort, 27Bh + Call PnP_Isolate + JZ PnP_DetectCardPort3 + Test AL, 1 + JZ PnP_DetectCardNotFound + Jmp PnP_DetectCardFound + +PnP_DetectCardPort3: + Mov PnP_ReadPort, 213h + Call PnP_Isolate + Test AL, 1 + JNZ PnP_DetectCardFound + +PnP_DetectCardNotFound: + StC + Jmp PnP_DetectEnd + +PnP_DetectCardFound: + ClC + +PnP_DetectEnd: ; Return PnP to wait for key state + Mov AX, 202h + Call PnP_WriteData + Mov DX, BasePort + JNC DetectWSSOK + +DetectPCI: +; Cmp DMA, 0FFFFh +; JNE DMAOverride + + Mov DMA, 1 ; Force DMA to 1. + +DMAOverride: + Mov EBX, 80000000h ; PCI output value. + Mov DX, 0CF8h + Mov CX, 32 + +DetectCardPCIBasePort1: + Mov EAX, EBX + Out DX, EAX + Add DX, 4 + In EAX, DX + Sub DX, 4 + Add EBX, 1 SHL 11 + + Cmp EAX, 8128Eh + LoopNE DetectCardPCIBasePort1 + + JNE DetectWSSFailure + + Add EBX, (3Ch) - (1 SHL 11) + Mov EAX, EBX + Out DX, EAX + Add DX, 4 + In EAX, DX ; AL = IRQ + Mov ECX, EAX + And AX, 0FFh + + JZ DetectWSSFailure + Cmp AL, 15 + JA DetectWSSFailure + + Cmp IRQ, 0FFFFh + JNE IRQSpecified + + Mov IRQ, AX + +; Mov OldIRQOffset, EBX +; Mov OldIRQData, ECX +; Mov UseOldIRQ, 1 + +IRQSpecified: + Sub DX, 4 + +; Get SAM9407IRQ + Add EBX, 1 SHL 8 + Mov EAX, EBX + Out DX, EAX + Add DX, 4 + In EAX, DX + Sub DX, 4 ; AL = IRQ. + + And AX, 0FFh + + PushA + + JZ NoSAM9407IRQ + Cmp AL, 15 + JA NoSAM9407IRQ + + Mov DL, AL + ShL DL, 4 + Mov CL, AL + And DX, 80h + Mov CH, 1 + Or DL, 21h + And CL, 7 + ShL CH, CL + In AL, DX + Or AL, CH + Out DX, AL + +NoSAM9407IRQ: + PopA + Push AX + + Add EBX, 10h-3Ch ; SAM9407 port + Mov EAX, EBX + Out DX, EAX + Add DX, 4 + In EAX, DX + Sub DX, 4 + And AX, 0FFEh + Mov SAM9407Port, AX + Pop CX + +; If SAM9407 Port not available, or IRQ = old IRQ, then set to ST42 mode. + Test AX, AX + JZ ST42Found + Cmp AX, 400h + JA ST42Found + Cmp CX, IRQ + JNE NoST42 + +ST42Found: +; Mov AX, '24' +; Mov Word Ptr O97A, AX +; Mov Word Ptr O97B, AX +; Mov Word Ptr O97C, AX +; Mov Word Ptr O97D, AX +; Mov Word Ptr O97E, AX +; Mov Word Ptr O97F, AX + Xor AX, AX + Mov SAM9407Port, AX + Mov ST42A, AX + Dec AX + Mov ST42B, AX + +NoST42: + Add EBX, 3 SHL 8 + Mov EAX, EBX + Out DX, EAX + Add DX, 4 + In EAX, DX + Sub DX, 4 + And AX, 0FFEh + Cmp AX, 400h + JB NoCS + + Xor AX, AX + +NoCS: + Mov CS4237Port, AX + + Sub EBX, 4 SHL 8 + +; Add EBX, 10h - 3Ch +; Add EBX, (10h) - (1 SHL 11) + Mov EAX, EBX + Out DX, EAX + Add DX, 4 + In EAX, DX + + And AX, 0FFEh + Mov DX, AX + + Cmp BasePort, 0FFFFh + JE BasePortNotSpecified + + Mov DX, BasePort + +BasePortnotSpecified: + Call PingWSS + JNC DetectWSSOK + +DetectWSSFailure: + StC + Ret + +DetectWSSOK: + Mov BasePort, DX + +CheckWSSOK: ; Check for IRQ + Add DX, 4 + + Mov AL, CODEC_INDEX_RDC + Out DX, AL + Inc DX + In AL, DX + Mov AH, AL + Dec DX + + Mov AL, CODEC_INDEX_LDC + Out DX, AL + Inc DX + In AL, DX + And AX, 3F3Fh + Neg AL + Neg AH + Add AL, 3Fh + Add AH, 3Fh + Mov [Word Ptr VolumeTable], AX + + Mov DX, CS4237Port + Test DX, DX + JZ DetectNoCS4237Port + + Add DX, 3 + + Mov AL, 3 + Out DX, AL + Inc DX + Mov AL, 0A0h + Out DX, AL + Dec DX ; Enable 3D stuff + + Mov AL, 2 + Out DX, AL + Inc DX + In AL, DX + Out DX, AL + Not AL + Mov AH, AL + And AL, 0Fh + ShR AH, 4 + + Mov [Word Ptr VolumeTable+31], AX + +DetectNoCS4237Port: + Mov EAX, 'Jeff' + ClC + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixModeTable Label Word + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + +Proc MixSamples ; Given DS:SI = info tables, CX = numchannels + + ; 1. Clean buffer + ; + update variables + ; 2. Update parameters + ; 3. Mix func + ; 4. Return + + Push CX + + Mov CX, BytesToMix + Mov ES, MixSegment + Mov DI, MIXTABLESIZE + Xor EAX, EAX + Mov DX, CX + Add CX, CX + + Mov MixTransferOffset, DI ; } Memory write + + Cmp Stereo, 0 + JE MixSamples1 + + Mov DX, CX + +MixSamples1: + Rep StosD ; } Memory write + Mov MixTransferRemaining, DX ; } + + Pop CX + +MixSamples2: + Test Byte Ptr [SI], 1 + JZ MixSamplesEnd2 + Cmp Byte Ptr [SI+36h], 100 + JE MixSamplesEnd2 + + Push CX + Mov CX, [SI] + + Test CH, 2 + JZ MixSamples3 + And Byte Ptr [SI], Not 1 + + Jmp MixSamplesEnd +; Cmp MixMode, 8 ; Is it volume ramping? +; JB MixSamplesEnd + +MixSamples3: + Test CL, 20h ; New freq? + JZ MixSamples5 + + Mov AX, [SI+10h] + Mov DX, [SI+12h] + Mov BX, MixSpeed + Cmp DX, BX + JAE MixSamplesHandleError + + Div BX + ShL EAX, 16 + Xor AX, AX + Div BX + Mov STEPVALUE, EAX + +MixSamples4: + Test CH, 1 + JZ MixSamples5 + + Mov DWord Ptr [SI+1Ch], 0 ; Current Volume = 0 + ; for volume sliding. +MixSamples5: + Test CX, 8440h ; New volume or panning? + JZ MixSamplesMix + + Xor AX, AX + Test CH, 8 ; Muted? + JNZ MixModeCommon + + Mov BX, MixMode + Add BL, Stereo + Add BX, BX + Jmp [CS:MixModeTable+BX] + +Mix0Mode: ; 16-bit mixing, no interpolation +Mix0ModeMono: ; and 16-bit mixing, interpolation + Mov AL, [SI+20h] + ShR AL, 1 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 30 ; Use left only-mixing for mono + Jmp MixModeCommon + +Mix0ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix0ModeSurround + + Mul Byte Ptr [SI+20h] ; Final volume + Add AX, 64 + ShR AX, 7 + Mov [SI+0Ch], AX ; Store into right volume + + Mov AL, 64 + Sub AL, [SI+37h] + Mul Byte Ptr [SI+20h] + Add AX, 64 + ShR AX, 7 + Mov [SI+0Eh], AX ; Left volume + + Mov CH, AL ; CH = left volume + Mov CL, [SI+0Ch] ; CL = right volume + Mov AX, 0 + + Test CX, CX + JZ MixModeCommon + + Mov AL, 30 ; Left only... + Test CL, CL + JZ MixModeCommon + + Mov AL, 60 + Test CH, CH + JZ MixModeCommon + + Mov AL, 90 + Cmp CL, CH + JZ MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix0ModeSurround: + Mov AL, [SI+20h] + ShR AL, 2 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 150 ; Surround + Jmp MixModeCommon + +Mix6ModeMono: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 8 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Test AX, AX + JZ MixModeCommon + Mov AX, 30 + Jmp MixModeCommon + +Mix6ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix6ModeSurround + + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Ch], AX ; Store into right volume + Mov BX, AX + ShL EAX, 16 + + Mov AL, 64 ; Do left volume + Sub AL, [SI+37h] ; AL = 64-FinalPan + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Eh], AX + + Mov ECX, EAX + + ; BX = right volume + ; CX = Left volume + Mov AX, 0 + Test ECX, ECX + JZ MixModeCommon + + Mov AL, 30 + Test BX, BX + JZ MixModeCommon + + Mov AL, 60 + Test CX, CX + JZ MixModeCommon + + Mov AL, 90 + Cmp CX, BX + JE MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix6ModeSurround: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 9 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + JZ MixModeCommon + Mov AX, 150 + Jmp MixModeCommon + +MixModeCommon: ; Requires AX = 30/60/90 etc. depending + ; On mixing mode type. + ; This will add 180 for 16-bit, + ; And sort out loop types. + Mov BL, [SI+0Ah] + Test Byte Ptr [SI+18h], 2 ; 16 bit? + JZ MixModeCommon1 + + Add AX, 180 + +MixModeCommon1: + Cmp BL, 8 + JB MixModeCommon3 ; No loop + JE MixModeCommon2 ; Forwards loop + + Add AX, 10 + +MixModeCommon2: + Add AX, 10 + +MixModeCommon3: + Add AX, Offset MixFunctionTables + Add AX, MixModeOffset + Mov [SI+8], AX ; Offset... + +MixSamplesMix: + Mov BX, [SI+8] ; BX = offset into + Mov EAX, [CS:BX+2] + Mov DWord Ptr PreMixFunction, EAX + Mov EAX, [CS:BX+6] + Mov DWord Ptr MixFunctionSeparateBackwards, EAX + + Mov AX, BytesToMix + Mov MixBlockSize, AX + Mov MixBufferOffset, MIXTABLESIZE + + Mov EAX, CURRENTPOSITION + Mov OLDPOSITION, EAX + + Call Word Ptr [CS:BX] + + And Word Ptr [SI], 0111100010001101b + Jmp MixSamplesEnd + +MixSamplesHandleError: + Mov Word Ptr [SI], 200h + + Test Byte Ptr [SI+3Ah], 80h + JNZ MixSamplesEnd + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Turn off channel + +MixSamplesEnd: + Pop CX + +MixSamplesEnd2: + Add SI, 128 + Dec CX + JNZ MixSamples2 + + Ret + +EndP MixSamples + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WSSIRQHandler + + PushAD + Push DS + Push ES + + ClD + + Mov AX, CS + Mov DS, AX + Assume DS:Driver + + Mov DX, [BasePort] + Add DX, 6 + In AL, DX + Test AL, 1 + JZ WSSAckIRQ2 + + Xor AL, AL + Out DX, AL + +WSSAckIRQ2: + Mov AL, 20h + Cmp IRQ, 8 + JB WSSAckIRQ1 + + Out 0A0h, AL + +WSSAckIRQ1: + Out 20h, AL + +DMAPort1 EQU $+1 + In AL, 1 + Mov BL, AL +DMAPort2 EQU $+1 + In AL, 1 + Mov BH, AL + + Xor AX, AX + + Cmp BX, DMABUFFERLENGTH/2 + JB WSSIRQHandler1 + + Mov AX, DMABUFFERLENGTH/2 + +WSSIRQHandler1: + CLD + ; OK... time to get next block + ; Check whether stereo thing is on.. + ; + LES DI, [ActualDMAPtr] + Add DI, AX + + Mov BX, DMASize ; BX = bytes required + ShR BX, 1 + ; BX = samples required + Mov BP, 8 ; Skip for mono + Mov CL, 14 ; Shift for mono + + Cmp Stereo, 0 + JE WSSIRQHandlerMono + + Mov BP, 4 ; Stereo skip value. + Dec CL + +WSSIRQHandlerMono: + Call SaveEMSPageFrame + + Cmp MixTransferRemaining, 0 + JNE WSSIRQHandler4 + Assume DS:Nothing + +WSSIRQHandler3: + Push BX + Push CX + Push BP + Push ES + Push DI + + Call Update + Call MixSamples + + Pop DI + Pop ES + Pop BP + Pop CX + Pop BX + +WSSIRQHandler4: + Mov DS, MixSegment + Mov SI, MixTransferOffset + Mov DX, BX ; DX = samples to transfer + Cmp DX, MixTransferRemaining + JBE WSSIRQHandler5 + + Mov DX, MixTransferRemaining + +WSSIRQHandler5: + Push DX + Cmp CS:Filter, 1 + JB WSSIRQHandler6 + JE WSSIRQHFilter + + Cmp CS:Stereo, 0 + JE WSSIRQ3QFilterMono + +WSSIRQ3QFilterStereo: + Push BX + + Mov EBX, FilterValue + Mov EBP, FilterValue2 + ShR DX, 1 + +WSSIRQ3QFilterStereo1: + Mov EAX, EBX + Mov ECX, EBP + Add EAX, [SI] + Add ECX, [SI+4] + SAR EAX, 1 + SAR ECX, 1 + Add EBX, EAX + Add EBP, ECX + SAR EBX, 1 + SAR EBP, 1 + + Mov EAX, EBX + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSS3QFilterStereoClip1 + Cmp EAX, 7FFFh + JG WSS3QFilterStereoClip2 + +WSSIRQ3QFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSS3QFilterStereoClip3 + Cmp EAX, 7FFFh + JG WSS3QFilterStereoClip4 + +WSSIRQ3QFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ WSSIRQ3QFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp WSSMixTransferEnd + +WSSIRQ3QFilterMono: + Push BX + + Mov EBX, FilterValue + +WSSIRQ3QFilterMono1: + Mov EAX, EBX + Add EAX, [SI] + SAR EAX, 1 + Add EBX, EAX + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL WSS3QFilterMonoClip1 + Cmp EAX, 7FFFh + JG WSS3QFilterMonoClip2 + +WSSIRQ3QFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ WSSIRQ3QFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp WSSMixTransferEnd + +WSSIRQHFilter: + Cmp CS:Stereo, 0 + JE WSSIRQHFilterMono + +WSSIRQHFilterStereo: + Push BX + + Mov EBX, FilterValue + Mov EBP, FilterValue2 + ShR DX, 1 + +WSSIRQHFilterStereo1: + Add EBX, [SI] + Add EBP, [SI+4] + + SAR EBX, 1 + SAR EBP, 1 + + Mov EAX, EBX + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSSHFilterStereoClip1 + Cmp EAX, 7FFFh + JG WSSHFilterStereoClip2 + +WSSIRQHFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSSHFilterStereoClip3 + Cmp EAX, 7FFFh + JG WSSHFilterStereoClip4 + +WSSIRQHFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ WSSIRQHFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp WSSMixTransferEnd + +WSSIRQHFilterMono: + Push BX + + Mov EBX, FilterValue + +WSSIRQHFilterMono1: + Add EBX, [SI] + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL WSSHFilterMonoClip1 + Cmp EAX, 7FFFh + JG WSSHFilterMonoClip2 + +WSSIRQHFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ WSSIRQHFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp WSSMixTransferEnd + +WSSIRQHandler6: + Mov EAX, [SI] + SAR EAX, CL + + Cmp EAX, -8000h + JL WSSIRQHandlerClip1 + Cmp EAX, 7FFFh + JG WSSIRQHandlerClip2 + +WSSIRQHandler7: + StosW ; } Memory write + + Add SI, BP + Dec DX + JNZ WSSIRQHandler6 + +WSSMixTransferEnd: + Pop DX + + Sub MixTransferRemaining, DX ; } Memory write + Sub BX, DX + JNZ WSSIRQHandler3 + + Mov MixTransferOffset, SI ; } Memory write + + Call RestoreEMSPageFrame + + Pop ES + Pop DS + PopAD + IRet + +WSSIRQHandlerClip1: + Mov AX, 8000h + Jmp WSSIRQHandler7 + +WSSIRQHandlerClip2: + Mov AX, 7FFFh + Jmp WSSIRQHandler7 + +WSSHFilterMonoClip1: + Mov AX, 8000h + Jmp WSSIRQHFilterMono2 + +WSSHFilterMonoClip2: + Mov AX, 7FFFh + Jmp WSSIRQHFilterMono2 + +WSSHFilterStereoClip1: + Mov AX, 8000h + Jmp WSSIRQHFilterStereo2 + +WSSHFilterStereoClip2: + Mov AX, 7FFFh + Jmp WSSIRQHFilterStereo2 + +WSSHFilterStereoClip3: + Mov AX, 8000h + Jmp WSSIRQHFilterStereo3 + +WSSHFilterStereoClip4: + Mov AX, 7FFFh + Jmp WSSIRQHFilterStereo3 + +WSS3QFilterMonoClip1: + Mov AX, 8000h + Jmp WSSIRQ3QFilterMono2 + +WSS3QFilterMonoClip2: + Mov AX, 7FFFh + Jmp WSSIRQ3QFilterMono2 + +WSS3QFilterStereoClip1: + Mov AX, 8000h + Jmp WSSIRQ3QFilterStereo2 + +WSS3QFilterStereoClip2: + Mov AX, 7FFFh + Jmp WSSIRQ3QFilterStereo2 + +WSS3QFilterStereoClip3: + Mov AX, 8000h + Jmp WSSIRQ3QFilterStereo3 + +WSS3QFilterStereoClip4: + Mov AX, 7FFFh + Jmp WSSIRQ3QFilterStereo3 + +EndP WSSIRQHandler + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Add DI, Offset IRQData + Mov BX, [CS:DI] + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset WSSIRQHandler + + XChg [ES:BX], EAX + Mov OldWSSIRQHandler, EAX + + Mov AX, IMR + And AX, [DI+2] + + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Pop ES + PopAD + + Ret + +EndP SetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Mov BX, [IRQData+DI] + + Mov EAX, OldWSSIRQHandler + Mov [ES:BX], EAX + + Pop ES + PopAD + + Ret + +EndP ResetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StopWSS + + Mov DX, BasePort + Add DX, 4 + + Mov AL, CODEC_INDEX_INTF + Out DX, AL + Inc DX + In AL, DX + And AL, Not INTF_PEN + Out DX, AL + + Inc DX + In AL, DX + Xor AL, AL + Out DX, AL + + Dec DX + Dec DX + + Mov AL, CODEC_INDEX_PIN + Out DX, AL + Inc DX + Xor AL, AL + Out DX, AL + + Ret + +EndP StopWSS + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StartWSS + + PushA + Push ES + Push DS + + Push CS + Pop DS + Assume DS:Driver + + ; Setup DMA + Mov BX, DMASegment + Xor AX, AX + Mov DX, DMA + Mov DI, DMABUFFERLENGTH + Call SetDMA + + LES DI, ActualDMAPtr + Xor AX, AX + Mov CX, DMABUFFERLENGTH/2 + Rep StosW + + Mov MixTransferRemaining, 0 + + Mov DX, BasePort + Call PingWSS + + Add DX, 4 + + Mov AL, CODEC_INDEX_PIN + Out DX, AL + Inc DX + Mov AL, PIN_IEN + Out DX, AL + Dec DX + + Mov AH, WSSMixConst ; Set format/frequency + Cmp Stereo, 0 + JE StartWSS1 + + Or AH, CDF_STEREO + +StartWSS1: + Mov AL, CODEC_MCE or CODEC_INDEX_CDF + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Call WaitCodec + + Mov AL, CODEC_INDEX_CDF + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Call WaitAutoCalibration + + ; Start playback + Mov AL, CODEC_INDEX_LWR_COUNT + Out DX, AL + Inc DX + + Mov AX, DMASize + ShR AX, 1 + + Cmp Stereo, 0 + JE StartWSS2 + + ShR AX, 1 + +StartWSS2: + Dec AX + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_UPR_COUNT + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_INTF + Out DX, AL + Inc DX + In AL, DX + Or AL, INTF_PEN + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_LDC + Out DX, AL + Inc DX + In AL, DX + And AL, Not LDC_LDM + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_RDC + Out DX, AL + Inc DX + In AL, DX + And AL, Not RDC_RDM + Out DX, AL + Dec DX + + Pop DS + Pop ES + PopA + + Ret + +EndP StartWSS + Assume DS:Nothing + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov SI, Offset RelocationTable + +RelocationFix: + LodsW + Test AX, AX + JZ RelocationEnd + Mov BX, AX + Mov [BX], DS + Jmp RelocationFix + + +RelocationEnd: + Call GetEMSPageFrame + Mov EMSPageFrame, AX + + In AL, 0A1h + Mov AH, AL + In AL, 21h + Mov IMR, AX + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + Call GetWSSMixConst + + Mov AX, 2643 + Mul MixSpeed + Add AX, 0FFFFh + AdC DX, 2080 + + Mov BX, (DMABUFFERLENGTH*2)/16 + Add BX, DX + + ; Allocate MixSegment first + Mov AH, 48h + + Int 21h + JNC InitSound1 + +InitSoundNoMemory: + Mov SI, Offset WSSNoMemoryMsg + Ret + +InitSound1: + Mov MixSegment, AX + Add AX, DX + Mov DMASegment, AX + + Call SetIRQ + Call GetTempo + Call SetTempo + + Mov DI, 1 + Call SetSAM9407 + + Mov SI, Offset WSSMsg + + Mov AX, BasePort + Mov BX, IRQ + Mov CX, DMA + + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Call ResetIRQ + Call SetIRQ + + Mov SI, Offset ReInitMsg + Mov BX, 40 + Call SetInfoLine + + Mov AL, Stereo + Call SetStereo + + Pop ES + Pop DS + PopA + + Ret + +EndP ReInitSound + Assume DS:Nothing + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, IMR + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Mov AX, MixSegment + Test AX, AX + JZ UnInitSound1 + + Mov ES, AX + Mov AH, 49h ; Release MixSegment + Int 21h + + Call StopWSS + Call ResetIRQ + +UnInitSound1: +; Cmp UseOldIRQ, 1 +; JNE UnInitSound2 +; +; Mov DX, 0CF8h +; Mov EAX, OldIRQOffset +; Out DX, EAX +; Add DX, 4 +; Mov EAX, OldIRQData +; Out DX, EAX +; +; UnInitSound2: + Call GotoHomeDirectory + + ; Now to save config into driver file. + Mov AX, 3D02h ; Read write access + Mov DX, Offset DriverName + Int 21h + JC SetMixMode1 + + Mov BX, AX + + Mov AX, 4200h + Xor CX, CX + Mov DX, Offset CONFIGURATIONOFFSET + Int 21h + JC SetMixMode2 + + Mov AH, 40h + Mov CX, CONFIGSIZE + Mov DX, Offset MixMode + Int 21h + +SetMixMode2: + Mov AH, 3Eh + Int 21h + +SetMixMode1: + Ret + +EndP UnInitSound + Assume DS:Nothing + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + Ret + +EndP Poll + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Push AX + Push BX + Push DX + + Push BX + + Mov AX, MixSpeed + Mov BX, AX + Xor DX, DX + + ShL AX, 1 + RCL DX, 1 ; DX:AX = Mixspeed*2 + + ShR BX, 1 ; BX = Mixspeed/2 + + Add AX, BX + AdC DX, 0 ; DX:AX = Mixspeed*2.5 + + Pop BX ; BX = tempo + Div BX + + Mov BytesToMix, AX + + Pop DX + Pop BX + Pop AX + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + PushA + Push DS + + Mov BX, AX ; BX = MixVolume + Mov CS:MixVolume, BX + + Mov AX, CS:MixSegment + Test AX, AX + JZ SetMixVolume2 + + Mov DS, AX + + Mov CX, MIXTABLESIZE/2 + Mov SI, MIXTABLESIZE-2; Starting point - working backwards + +SetMixVolume1: + Mov AX, CX + + Dec AX ; AH = volume, AL = wave value. + Xor DX, DX + XChg AH, DL ; DL = Volume, AX = wave value + CBW + + IMul DX ; DX:AX = Volume * Wave Value + ; Ranges -8192->8128 + + IMul BX ; DX:AX = Volume * Wave Value * Mixing Volume + ; Ranges -1048576->1040384 + + Add AX, 64 + AdC DX, 0 + + ShRD AX, DX, 7 + Mov [SI], AX + Sub SI, 2 + + Loop SetMixVolume1 + +SetMixVolume2: + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS: RecalculateAllVolumes + + Pop DS + PopA + + Ret + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc RecalculateAllFrequencies + + Call GetChannelTables + +RecalculateAllFrequencies1: + Or Byte Ptr [SI], 32 + + Add SI, 128 + Dec CX + JNZ RecalculateAllFrequencies1 + + Ret + +EndP RecalculateAllFrequencies + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Mov CS:Stereo, AL + Cmp CS:MixSegment, 0 + JE SetStereo1 + + Push AX + + Call StopWSS + Call StartWSS + + Call RecalculateAllFrequencies + + Pop DI + And DI, 1 + Add DI, 31 + Call SetSAM9407 + + Mov DI, 2 +SetStereo2: + Call SetSAM9407 + Inc DI + Cmp DI, 30 + JBE SetStereo2 + +SetStereo1: + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include loadsam.inc + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset WSS16ScreenList + + ClC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far + + Xor AH, AH + Mov AL, [CS:VolumeTable+DI] + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UpdateSoundcardVariables + + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov DX, BasePort + Add DX, 4 + + Mov AL, CODEC_INDEX_LDC + Out DX, AL + Inc DX + Mov AX, 3F3Fh + Sub AX, [Word Ptr VolumeTable] + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_RDC + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + + Mov DX, CS4237Port + Test DX, DX + JZ UpdateSoundCardVariables1 + + Add DX, 3 + + Mov AL, 3 + Out DX, AL + Inc DX + Mov AL, 0A0h + Out DX, AL + Dec DX + + Mov AL, 2 + Out DX, AL + + Mov AX, [Word Ptr VolumeTable+31] + ShL AH, 4 + Inc DX + Or AL, AH + Not AL + Out DX, AL + +UpdateSoundCardVariables1: + + Pop DS + PopA + + Ret + +EndP UpdateSoundcardVariables + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far + + Mov [CS:VolumeTable+DI], AL + Cmp DI, 31 + JAE SetVariable1 + Cmp DI, 2 + JB SetVariable1 + + Call SetSAM9407 + Ret + +SetVariable1: + Call UpdateSoundcardVariables + Ret + +EndP SetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. +StopAfterPlay DW 0 +DefaultChannels DW 64 +DriverFlags DW 0 + DW 4 Dup (0) + + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/ST97PNP.ASM b/SoundDrivers/ST97PNP.ASM new file mode 100755 index 0000000..8fb2fcb --- /dev/null +++ b/SoundDrivers/ST97PNP.ASM @@ -0,0 +1,2623 @@ +; +; Analog Device's AD1816 +; + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;********************************** + +PNPSERIALID EQU 0FFFFFFFFh +PNPVENDORID EQU 80719304h + +STEREOENABLED EQU 1 +DMABUFFERLENGTH EQU 8192 +MIXRESOLUTION EQU 32 ; 32 bit mixing for +MIXTABLESIZE EQU 2*256*65 +DATAFLAG EQU 200h +ACKFLAG EQU 300h + +Debug DW 0 +Debug2 DW 0 +DMASize DW 2048 + +ESSMsg DB "Sound Track '97 PnP found", 13 + DB "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, DMA ", 0FDh, "D", 0 + +ESSNoMemoryMsg DB "Sound Track '97 PnP found", 13 + DB "Error: Insufficient memory", 0 + +ReinitMsg DB "Sound Track '97 PnP reinitialised", 0 + +DriverName DB "ITSTPNP.DRV", 0 + +Forced DB 0 +Stereo DB 0 +MixVolume DW 0 + +BytesToMix DW 1000 +ESSMixConst DB 0 + +MixSegment DW 0 +DMASegment DW 0 + +MixTransferOffset DW 0 +MixTransferRemaining DW 0 + +CONFIGURATIONOFFSET EQU $+128 +CONFIGSIZE EQU 6 +MixMode DW 0 +MixModeOffset DW 0 +Filter DW 0 +VolumeTable DB 56, 56 + DB 60h, 60h, 0Ch ; Low Band + DB 40h, 40h, 1Bh ; Med Low Band + DB 40h, 40h, 72h ; Med High Band + DB 60h, 60h, 40h ; High Band + DB 0, 0, 0 ; Echo + DB 0, 2 ; Surround + DB 0, 90h, 4, 7Fh, 22h ; Reverb + DB 0, 90h, 2, 40h, 9, 3, 13h ; Chorus + DB 0, 0 ; Phat Stereo Stuff + +IMR DW 0 +OldESSIRQHandler DD 0 + +FilterValue DD 0 +FilterValue2 DD 0 + +SAM9407Reset DW 66 + DW 1BEh, 16Fh, 7Fh, 7Fh, ACKFLAG ; Audio in on + DW 1BEh, 168h, 7Fh, 7Fh, ACKFLAG ; Echo on + DW 1BEh, 16Ch, 7Fh, 7Fh, ACKFLAG ; Reverb on + DW 1BEh, 16Dh, 7Fh, 7Fh, ACKFLAG ; Chorus on + DW 1BEh, 16Bh, 0, 0, ACKFLAG ; Equalizer type + DW 1BEh, 16Eh, 7Fh, 7Fh, ACKFLAG ; Surround on + DW 1BEh, 165h, 7Fh, 7Fh ; Post eff on Audio in + DW 1BEh, 166h, 7Fh, 7Fh ; Post eff on reverb, chorus + DW 1BEh, 133h, 0, 0 ; 2 Speaker + DW 1BEh, 120h, 7Fh, 7Fh ; Stereo input 2 + DW 1BEh, 134h, 0FFh, 0FFh ; Left gain + DW 1BEh, 135h, 0FFh, 0FFh ; Right gain + DW 1BEh, 136h, 0, 0 ; Left pan + DW 1BEh, 137h, 7Fh, 7Fh ; Right pan + DW 1BEh, 107h, 0FFh, 0FFh ; Master volume + +SAM9407EqLBL DW 4 + DW 1BEh, 110h, DATAFLAG, 60h +SAM9407EqLBR DW 4 + DW 1BEh, 114h, DATAFLAG, 60h +SAM9407EqLBF DW 4 + DW 1BEh, 118h, DATAFLAG, 0Ch +SAM9407EqMLBL DW 4 + DW 1BEh, 111h, DATAFLAG, 40h +SAM9407EqMLBR DW 4 + DW 1BEh, 115h, DATAFLAG, 40h +SAM9407EqMLBF DW 4 + DW 1BEh, 119h, DATAFLAG, 1Bh +SAM9407EqMHBL DW 4 + DW 1BEh, 112h, DATAFLAG, 40h +SAM9407EqMHBR DW 4 + DW 1BEh, 116h, DATAFLAG, 40h +SAM9407EqMHBF DW 4 + DW 1BEh, 11Ah, DATAFLAG, 72h +SAM9407EqHBL DW 4 + DW 1BEh, 113h, DATAFLAG, 60h +SAM9407EqHBR DW 4 + DW 1BEh, 117h, DATAFLAG, 60h +SAM9407EqHBF DW 4 + DW 1BEh, 11Bh, DATAFLAG, 0Ch +SAM9407EchoLevel DW 4 + DW 1BEh, 128h, DATAFLAG, 0 +SAM9407EchoTime DW 4 + DW 1BEh, 129h, DATAFLAG, 2Bh +SAM9407EchoFeed DW 4 + DW 1BEh, 12Ah, DATAFLAG, 40h +SAM9407SurroundVolume DW 4 + DW 1BEh, 130h, DATAFLAG, 0 +SAM9407SurroundDelay DW 4 + DW 1BEh, 131h, DATAFLAG, 2 +SAM9407ReverbSend DW 4 + DW 1BEh, 127h, DATAFLAG, 0 +SAM9407ReverbVolume DW 3 + DW 1BEh, 13Ah, DATAFLAG +SAM9407ReverbType DW 4 + DW 1BEh, 169h, DATAFLAG, 4 +SAM9407ReverbTime DW 3 + DW 1BEh, 178h, DATAFLAG +SAM9407ReverbFeedback DW 3 + DW 1BEh, 179h, DATAFLAG +SAM9407ChorusSend DW 4 + DW 1BEh, 124h, DATAFLAG, 0 +SAM9407ChorusVolume DW 3 + DW 1BEh, 13Bh, DATAFLAG +SAM9407ChorusType DW 4 + DW 1BEh, 16Ah, DATAFLAG, 2 +SAM9407ChorusDelay DW 3 + DW 1BEh, 174h, DATAFLAG +SAM9407ChorusFeedback DW 3 + DW 1BEh, 175h, DATAFLAG +SAM9407ChorusRate DW 3 + DW 1BEh, 176h, DATAFLAG +SAM9407ChorusDepth DW 3 + DW 1BEh, 177h, DATAFLAG +SAM9407Mono DW 4 + DW 1BEh, 132h, 7Fh, 0 +SAM9407Stereo DW 4 + DW 1BEh, 132h, 0, 0 + +SAM9407Strings DW Offset SAM9407Reset ;1 + DW Offset SAM9407EqLBL, Offset SAM9407EqLBR + DW Offset SAM9407EqLBF + DW Offset SAM9407EqMLBL, Offset SAM9407EqMLBR + DW Offset SAM9407EqMLBF + DW Offset SAM9407EqMHBL, Offset SAM9407EqMHBR + DW Offset SAM9407EqMHBF + DW Offset SAM9407EqHBL, Offset SAM9407EqHBR + DW Offset SAM9407EqHBF + DW Offset SAM9407EchoLevel ; 14 + DW Offset SAM9407EchoTime + DW Offset SAM9407EchoFeed + DW Offset SAM9407SurroundVolume ; 17 + DW Offset SAM9407SurroundDelay + DW Offset SAM9407ReverbSend ; 19 + DW Offset SAM9407ReverbVolume + DW Offset SAM9407ReverbType + DW Offset SAM9407ReverbTime + DW Offset SAM9407ReverbFeedback ; 23 + DW Offset SAM9407ChorusSend ; 24 + DW Offset SAM9407ChorusVolume + DW Offset SAM9407ChorusType + DW Offset SAM9407ChorusDelay + DW Offset SAM9407ChorusFeedback + DW Offset SAM9407ChorusRate + DW Offset SAM9407ChorusDepth ; 30 + DW Offset SAM9407Mono ; 31 + DW Offset SAM9407Stereo + +IRQData Label Word + DW 20h, 1111111111111110b ; IRQ 0 + DW 24h, 1111111111111101b ; IRQ 1 + DW 28h, 1111110111111011b ; IRQ 2 + DW 2Ch, 1111111111110111b ; IRQ 3 + DW 30h, 1111111111101111b ; IRQ 4 + DW 34h, 1111111111011111b ; IRQ 5 + DW 38h, 1111111110111111b ; IRQ 6 + DW 3Ch, 1111111101111111b ; IRQ 7 + DW 1C0h, 1111111011111011b ; IRQ 8 + DW 1C4h, 1111110111111011b ; IRQ 9 + DW 1C8h, 1111101111111011b ; IRQ 10 + DW 1CCh, 1111011111111011b ; IRQ 11 + DW 1D0h, 1110111111111011b ; IRQ 12 + DW 1D4h, 1101111111111011b ; IRQ 13 + DW 1D8h, 1011111111111011b ; IRQ 14 + DW 1DCh, 0111111111111011b ; IRQ 15 + +WSSScreenList Label + DW 16 + DW Near Ptr IdleFunctionList + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr WSSHeaderLine + + DW Near Ptr DriverText + + DW Near Ptr MixModeText + DW Near Ptr MixModeButton1 ; 6 + DW Near Ptr MixModeButton2 ; + DW Near Ptr MixModeButton3 ; 8 + DW Near Ptr MixModeButton4 ; 9 + + DW Near Ptr FilterText + DW Near Ptr FilterButton1 ; 11 + DW Near Ptr FilterButton2 + DW Near Ptr FilterButton3 + + DW Near Ptr VolumeText + DW Near Ptr VolumeBox1 + + DW Near Ptr MasterVolumeLeft ; 16 + DW Near Ptr MasterVolumeRight ; 17 + + DW Near Ptr EmptyObject + DW Near Ptr EmptyObject + DW Near Ptr EmptyObject + + DW Near Ptr SAM9407PortText ; 21 + DW Near Ptr SAM9407ParametersText + DW Near Ptr SAM9407ParametersBox + + DW Near Ptr EqLBL ; 24 + DW Near Ptr EqLBR + DW Near Ptr EqLBF + + DW Near Ptr EqMLBL + DW Near Ptr EqMLBR + DW Near Ptr EqMLBF + + DW Near Ptr EqMHBL + DW Near Ptr EqMHBR + DW Near Ptr EqMHBF + + DW Near Ptr EqHBL + DW Near Ptr EqHBR + DW Near Ptr EqHBF + + DW Near Ptr EchoLevel ; 33 + DW Near Ptr EchoTime + DW Near Ptr EchoFeedback + + DW Near Ptr SurroundVolume + DW Near Ptr SurroundDelay + + DW Near Ptr ReverbSend ; 38 + DW Near Ptr ReverbVolume + DW Near Ptr ReverbType + DW Near Ptr ReverbTime + DW Near Ptr ReverbFeedback + + DW Near Ptr ChorusSend + DW Near Ptr ChorusVolume + DW Near Ptr ChorusType + DW Near Ptr ChorusDelay + DW Near Ptr ChorusFeedback + DW Near Ptr ChorusRate + DW Near Ptr ChorusDepth + + + DW 0 + +WSSHeaderLine DW 10 + DB "Sound Track '97 PnP Codec Driver", 0 + +EmptyObject DW 1 + DB 0, 0 + DB 0 + DB 0 + +DriverText DW 1 + DB 28, 48 + DB 21h + DB "Sound Track Codec Driver 1.0 for Impulse Tracker", 0 + +SAM9407PortText DW 1 + DB 28, 47 + DB 21h + DB "Sound Track SAM9407 Port ", 0FDh, "Xh", 0 +SAM9407Port DW 0 + +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +IdleFunctionList DD 0 + DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +VolumeText DW 1 + DB 2, 14 + DB 20h + DB "Master Volume Left", 13 + DB "Master Volume Right", 0 + +VolumeBox1 DW 0 + DB 21, 13, 31, 16 + DB 25 + +MasterVolumeLeft DW 14 + DB 22, 14 + DW 0, 63 + DW 9, 0 + DW 0FFFFh, 17, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 8 + +MasterVolumeRight DW 14 + DB 22, 15 + DW 0, 63 + DW 9, 1 + DW 16, 6, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 8 + +MixModeText DW 1 + DB 2, 17 + DB 20h + DB "Mixing Rate: ", 0FDh, "D", 13, 13 + DB "Mixing mode", 0 +MixSpeed DW 48000 + +MixModeButton1 DW 2 + DW 17, 7, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment1 DW 0 + DW 0 + DW Offset SetMixMode +DriverSegment2 DW 0 + DB 3, 21, 32, 23, 8 + DB 0 + DB " 16 Bit, Non-Interpolated", 0 + +MixModeButton2 DW 2 + DW 6, 8, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment3 DW 0 + DW 2 + DW Offset SetMixMode +DriverSegment4 DW 0 + DB 3, 24, 32, 26, 8 + DB 0 + DB " 16 Bit, Interpolated", 0 + +MixModeButton3 DW 2 + DW 7, 9, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment5 DW 0 + DW 4 + DW Offset SetMixMode +DriverSegment6 DW 0 + DB 3, 27, 32, 29, 8 + DB 0 + DB " 32 Bit, Interpolated", 0 + +MixModeButton4 DW 2 + DW 8, 11, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment7 DW 0 + DW 6 + DW Offset SetMixMode +DriverSegment8 DW 0 + DB 3, 30, 32, 32, 8 + DB 0 + DB " 32 Bit, Ultra Quality", 0 + +FilterText DW 1 + DB 2, 34 + DB 20h + DB "Filter mode", 0 + +FilterButton1 DW 2 + DW 9, 12, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment9 DW 0 + DW 0 + DW Offset SetFilter +DriverSegment10 DW 0 + DB 3, 36, 29, 38, 8 + DB 0 + DB " No Filter", 0 + +FilterButton2 DW 2 + DW 11, 13, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment11 DW 0 + DW 1 + DW Offset SetFilter +DriverSegment12 DW 0 + DB 3, 39, 29, 41, 8 + DB 0 + DB " 50% Filter", 0 + +FilterButton3 DW 2 + DW 12 +ST42B DW 24, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment13 DW 0 + DW 2 + DW Offset SetFilter +DriverSegment14 DW 0 + DB 3, 42, 29, 44, 8 + DB 0 + DB " 75% Filter", 0 + +SAM9407ParametersText DW 1 + DB 36, 14 + DB 20h + DB "Low Band Left", 13 + DB "Low Band Right", 13 + DB "Low Band Frequency", 13 + DB "Med Low Band Left", 13 + DB "Med Low Band Right", 13 + DB "Med Low Band Frequency", 13 + DB "Med High Band Left", 13 + DB "Med High Band Right", 13 + DB "Med High Band Frequency", 13 + DB "High Band Left", 13 + DB "High Band Right", 13 + DB "High Band Frequency", 13 + DB "Echo Level", 13 + DB "Echo Time", 13 + DB "Echo Feedback", 13 + DB "Surround Volume", 13 + DB "Surround Delay", 13 + DB "Reverb Send", 13 + DB "Reverb Volume", 13 + DB "Reverb Type", 13 + DB "Reverb Time", 13 + DB "Reverb Feedback", 13 + DB "Chorus Send", 13 + DB "Chorus Volume", 13 + DB "Chorus Type", 13 + DB "Chorus Delay", 13 + DB "Chorus Feedback", 13 + DB "Chorus Rate", 13 + DB "Chorus Depth", 13 + DB 0 + +EqLBL DW 14 + DB 60, 14 + DW 0, 127 + DW 9, 2 + DW 13, 25, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqLBR DW 14 + DB 60, 15 + DW 0, 127 + DW 9, 3 + DW 24, 26, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqLBF DW 14 + DB 60, 16 + DW 0, 127 + DW 9, 4 + DW 25, 27, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqMLBL DW 14 + DB 60, 17 + DW 0, 127 + DW 9, 5 + DW 26, 28, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqMLBR DW 14 + DB 60, 18 + DW 0, 127 + DW 9, 6 + DW 27, 29, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqMLBF DW 14 + DB 60, 19 + DW 0, 127 + DW 9, 7 + DW 28, 30, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqMHBL DW 14 + DB 60, 20 + DW 0, 127 + DW 9, 8 + DW 29, 31, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqMHBR DW 14 + DB 60, 21 + DW 0, 127 + DW 9, 9 + DW 30, 32, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqMHBF DW 14 + DB 60, 22 + DW 0, 127 + DW 9, 10 + DW 31, 33, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqHBL DW 14 + DB 60, 23 + DW 0, 127 + DW 9, 11 + DW 32, 34, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqHBR DW 14 + DB 60, 24 + DW 0, 127 + DW 9, 12 + DW 33, 35, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EqHBF DW 14 + DB 60, 25 + DW 0, 127 + DW 9, 13 + DW 34, 36, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EchoLevel DW 14 + DB 60, 26 + DW 0, 127 + DW 9, 15 + DW 35, 37, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EchoTime DW 14 + DB 60, 27 + DW 0, 127 + DW 9, 14 + DW 36, 38, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +EchoFeedback DW 14 + DB 60, 28 + DW 0, 127 + DW 9, 16 + DW 37, 39, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +SurroundVolume DW 14 + DB 60, 29 + DW 0, 255 + DW 9, 17 + DW 38, 40, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +SurroundDelay DW 14 + DB 60, 30 + DW 0, 127 + DW 9, 18 + DW 39, 41, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ReverbSend DW 14 + DB 60, 31 + DW 0, 127 + DW 9, 19 + DW 40, 42, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ReverbVolume DW 14 + DB 60, 32 + DW 0, 255 + DW 9, 20 + DW 41, 43, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + + +ReverbType DW 14 + DB 60, 33 + DW 0, 7 + DW 9, 21 + DW 42, 44, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ReverbTime DW 14 + DB 60, 34 + DW 0, 127 + DW 9, 22 + DW 43, 45, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ReverbFeedback DW 14 + DB 60, 35 + DW 0, 127 + DW 9, 23 + DW 44, 46, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ChorusSend DW 14 + DB 60, 36 + DW 0, 127 + DW 9, 24 + DW 45, 47, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ChorusVolume DW 14 + DB 60, 37 + DW 0, 255 + DW 9, 25 + DW 46, 48, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ChorusType DW 14 + DB 60, 38 + DW 0, 7 + DW 9, 26 + DW 47, 49, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ChorusDelay DW 14 + DB 60, 39 + DW 0, 127 + DW 9, 27 + DW 48, 50, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ChorusFeedback DW 14 + DB 60, 40 + DW 0, 127 + DW 9, 28 + DW 49, 51, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ChorusRate DW 14 + DB 60, 41 + DW 0, 127 + DW 9, 29 + DW 50, 52, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +ChorusDepth DW 14 + DB 60, 42 + DW 0, 127 + DW 9, 30 + DW 51, 0FFFFh, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + DW 14 + +SAM9407ParametersBox DW 0 + DB 59, 13, 75, 43 + DB 25 + +; ÄÄ MixingRoutines ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixBufferPos DW 0 + +include dmasirq.inc +include mix.inc +include m12bit.mix +include m12biti.mix +include m32bit.mix +include m32biti.mix + +MixFunctionTables Label + +include m12bit.inc ; contains the tables +include m12biti.inc +include m32bit.inc +include m32biti.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +RelocationTable Label Word + DW Offset DriverSegment1, Offset DriverSegment2 + DW Offset DriverSegment3, Offset DriverSegment4 + DW Offset DriverSegment5, Offset DriverSegment6 + DW Offset DriverSegment7, Offset DriverSegment8 + DW Offset DriverSegment9, Offset DriverSegment10 + DW Offset DriverSegment11, Offset DriverSegment12 + DW Offset DriverSegment13, Offset DriverSegment14 + DW 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc AD1816Wait + + PushA + Xor CX, CX + Mov DX, CS:BasePort + +AD1816Wait1: + In AL, DX + Test AL, 80h + LoopZ AD1816Wait1 + + PopA + Ret + +EndP AD1816Wait + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc AD1816RegisterOut ; AL = indirect register, BX = contents + + Call AD1816Wait + + Push DX + PushF + + ClI + + Mov DX, CS:BasePort + Out DX, AL + Add DL, 2 + + Mov AL, BL + Out DX, AL + Inc DX + Mov AL, BH + Out DX, AL + + PopF + Pop DX + + Ret + +EndP AD1816RegisterOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc AD1816RegisterIn ; AL = register + ; Returns BX + + Call AD1816Wait + + Push AX + Push DX + + Mov DX, CS:BasePort + Out DX, AL + Add DL, 2 + + In AL, DX + Mov BL, AL + Inc DX + In AL, DX + Mov BH, AL + + Pop DX + Pop AX + + Ret + +EndP AD1816RegisterIn + +; ÄÄ SAM9407InByte ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SAM9407InByte ; Returns AL + + Push CX DX + + Mov DX, CS:SAM9407Port + Inc DX + + Mov CX, 1000h + +SAM9407InByte1: + In AL, DX + Test AL, 80h + LoopNZ SAM9407InByte1 + + Dec DX + In AL, DX + Pop DX CX + + Ret + +EndP SAM9407InByte + +; ÄÄ ST97SendByte ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SAM9407SendByte ; DX = port, AL = data + + Push AX CX DX + Mov DX, CS:SAM9407Port + Mov CX, 1000h + Inc DX + +SAM9407SendByte1: + In AL, DX + Test AL, 40h + LoopNZ SAM9407SendByte1 + + Pop DX CX AX + + Out DX, AL + + Ret + +EndP SAM9407SendByte + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetSAM9407 ; DI = index. 1 = full reinit. + + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + LEA SI, [SAM9407Strings+EDI+EDI-2] + Mov SI, [SI] + + LodsW + Mov CX, AX + +SetSAM9407_1: +; AH = 0 = normal data, 1 = command, 2 = param, 3 = ack. + + Mov DX, SAM9407Port + Test DX, DX + JZ NoSAM9407 + + LodsW + + Cmp AH, 2 + JB SetSAM9407_3 + JA SetSAM9407_4 + + Mov AL, [VolumeTable+DI] + Jmp SetSAM9407_2 + +SetSAM9407_4: + Call SAM9407InByte + Test AL, AL + JNZ SetSAM9407_4 + Jmp SetSAM9407_5 + +SetSAM9407_3: + And AH, 1 + Add DL, AH + +SetSAM9407_2: + Call SAM9407SendByte + +SetSAM9407_5: + Dec CX + JNZ SetSAM9407_1 + + +NoSAM9407: + Pop DS + PopA + + Ret + +EndP SetSAM9407 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixMode Far + + Push CS + Pop ES + Mov DI, Offset MixMode + + Ret + +EndP GetMixMode + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetFilter Far + + Push CS + Pop ES + Mov DI, Offset Filter + + Ret + +EndP GetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetFilter Far + + Mov AX, [SI+22] + Mov CS:FilterValue, 0 + Mov CS:Filter, AX + + Mov AX, 1 + Ret + +EndP SetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixMode Far + + Mov AX, [SI+22] + + ClI + + Mov CS:MixMode, AX + + Mov BX, 180 + Mul BX + Mov CS:MixModeOffset, AX + + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS:RecalculateAllVolumes + + StI + + Mov AX, 1 + Ret + +EndP SetMixMode + Assume DS:Nothing + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +PnP_SerialID DD 0 +PnP_VendorID DD 0 +PnP_ReadPort DW 0 +PnP_CSN DB 0 +PnP_CardFound DB 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_Delay + Assume DS:Driver + + Push AX CX + + Mov CX, 180h +PnP_Delay1: + In AL, 21h + Loop PnP_Delay1 + + Pop CX AX + Ret + +EndP PnP_Delay + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_WriteData + + Mov DX, 279h + Out DX, AL + + Mov AL, AH + Mov DH, 0Ah + Out DX, AL + Ret + +EndP PnP_WriteData + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_ReadData + + Mov DX, 279h + Out DX, AL + + Mov DX, PnP_ReadPort + In AL, DX + + Ret + +EndP PnP_ReadData + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PnP_Isolate + + Mov AX, 402h + Call Pnp_WriteData ; Reset CSNs + +PnP_IsolateNextCard: + Mov AX, 0003h + Call PnP_WriteData ; Wake[0] + + Mov AX, PnP_ReadPort + ShL AX, 6 + Xor AL, AL + Call PnP_WriteData ; Set Read Data port. + + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + + Mov AL, 1 ; Serial Isolation + Mov DX, 279h + Out DX, AL + + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + Call PnP_Delay + + Mov BL, 6Ah + Mov CX, 64 + Mov DX, PnP_ReadPort + + ClI + +PnP_Isolate1: + ShR PnP_SerialID, 1 + RCR PnP_VendorID, 1 + + Mov BH, BL + ShR BH, 1 + Xor BH, BL + ShR BX, 1 + + In AL, DX + Mov AH, AL + Call PnP_Delay + In AL, DX + Call PnP_Delay + + Cmp AX, 55AAh + JNE PnP_Isolate2 + + Xor BL, 80h + Or PnP_SerialID, 80000000h + +PnP_Isolate2: + Dec CX + JNZ PnP_Isolate1 + + Mov CX, 8 + Xor BH, BH + +PnP_Isolate3: + ShR BH, 1 + + In AL, DX + Mov AH, AL + Call PnP_Delay + In AL, DX + Call PnP_Delay + Cmp AX, 55AAh + JNE PnP_Isolate4 + + Or BH, 80h + +PnP_Isolate4: + Dec CX + JNZ PnP_Isolate3 + + StI + + Cmp BL, BH ; Matching Checksum? + JNE PnP_IsolateFinished + + ; assign CSN + Inc PnP_CSN + + Mov AL, 6 + MOv AH, PnP_CSN + Call PnP_WriteData + + Cmp PnP_VendorID, PNPVENDORID + JNE PnP_IsolateNextCard + Cmp PnP_SerialID, PNPSERIALID + JNE PnP_IsolateNextCard + + Mov AL, 3 + Call PnP_WriteData + Mov AX, 007h + Call PnP_WriteData + + Mov AL, 64h + Call PnP_ReadData + Mov AH, AL + Mov AL, 65h + Call PnP_ReadData ; AX = address. + Cmp BasePort, 0FFFFh + JE PnPBasePortOK + + Cmp BasePort, AX + JNE PnP_IsolateNextCard + +PnPBasePortOK: + Mov BasePort, AX + + Mov AL, 70h + Call PnP_ReadData ; AL[3:0] = IRQ + And AX, 15 + JZ PnP_IsolateNextCard + Mov IRQ, AX + + Mov AL, 74h + Call PnP_ReadData ; AL[2:0] = DMA + And AX, 7 + Cmp AL, 4 + JE PnP_IsolateNextCard + Mov DMA, AX + + Mov AX, 307h ; LDN 1 - MIDI device + Call PnP_WriteData + + Mov AL, 60h + Call PnP_ReadData + Mov AH, AL + Mov AL, 61h + Call PnP_ReadData ; AX = address. + Test AX, AX + JZ PnP_IsolateNextCard + + Mov SAM9407Port, AX + + Mov Pnp_CardFound, 1 + Jmp PnP_IsolateNextCard + +PnP_IsolateFinished: + Mov AL, PnP_CSN + ShL AL, 1 + Or AL, PnP_CardFound + + Ret + +EndP PnP_Isolate + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far ; returns carry clear if succesful + + Push CS + Pop DS + + Xor AL, AL + Mov DX, 279h + Out DX, AL + Out DX, AL + + Mov AL, 6Ah ; Starting value + Mov CX, 32 + +PnP_InitiationKeyLoop: + Out DX, AL + + Mov AH, AL + ShR AH, 1 + Xor AH, AL + ShR AX, 1 + + Dec CX + JNZ PnP_InitiationKeyLoop + +; Try three ports before concluding no PnP cards: 20Fh, 27Bh, 213h + +PnP_DetectCardPort1: + Mov PnP_ReadPort, 20Fh + Call PnP_Isolate + JZ PnP_DetectCardPort2 + Test AL, 1 + JZ PnP_DetectCardNotFound + Jmp PnP_DetectCardFound + +PnP_DetectCardPort2: + Mov PnP_ReadPort, 27Bh + Call PnP_Isolate + JZ PnP_DetectCardPort3 + Test AL, 1 + JZ PnP_DetectCardNotFound + Jmp PnP_DetectCardFound + +PnP_DetectCardPort3: + Mov PnP_ReadPort, 213h + Call PnP_Isolate + Test AL, 1 + JNZ PnP_DetectCardFound + +PnP_DetectCardNotFound: + StC + Jmp PnP_DetectEnd + +PnP_DetectCardFound: + ClC + +PnP_DetectEnd: ; Return PnP to wait for key state + Mov AX, 202h + Call PnP_WriteData + Mov EAX, 'Jeff' + + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixModeTable Label Word + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + +Proc MixSamples ; Given DS:SI = info tables, CX = numchannels + + ; 1. Clean buffer + ; + update variables + ; 2. Update parameters + ; 3. Mix func + ; 4. Return + + Push CX + + Mov CX, BytesToMix + Mov ES, MixSegment + Mov DI, MIXTABLESIZE + Xor EAX, EAX + Mov DX, CX + Add CX, CX + + Mov MixTransferOffset, DI ; } Memory write + + Cmp Stereo, 0 + JE MixSamples1 + + Mov DX, CX + +MixSamples1: + Rep StosD ; } Memory write + Mov MixTransferRemaining, DX ; } + + Pop CX + +MixSamples2: + Test Byte Ptr [SI], 1 + JZ MixSamplesEnd2 + Cmp Byte Ptr [SI+36h], 100 + JE MixSamplesEnd2 + + Push CX + Mov CX, [SI] + + Test CH, 2 + JZ MixSamples3 + And Byte Ptr [SI], Not 1 + + Jmp MixSamplesEnd +; Cmp MixMode, 8 ; Is it volume ramping? +; JB MixSamplesEnd + +MixSamples3: + Test CL, 20h ; New freq? + JZ MixSamples5 + + Mov AX, [SI+10h] + Mov DX, [SI+12h] + Mov BX, MixSpeed + Cmp DX, BX + JAE MixSamplesHandleError + + Div BX + ShL EAX, 16 + Xor AX, AX + Div BX + Mov STEPVALUE, EAX + +MixSamples4: + Test CH, 1 + JZ MixSamples5 + + Mov DWord Ptr [SI+1Ch], 0 ; Current Volume = 0 + ; for volume sliding. +MixSamples5: + Test CX, 8440h ; New volume or panning? + JZ MixSamplesMix + + Xor AX, AX + Test CH, 8 ; Muted? + JNZ MixModeCommon + + Mov BX, MixMode + Add BL, Stereo + Add BX, BX + Jmp [CS:MixModeTable+BX] + +Mix0Mode: ; 16-bit mixing, no interpolation +Mix0ModeMono: ; and 16-bit mixing, interpolation + Mov AL, [SI+20h] + ShR AL, 1 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 30 ; Use left only-mixing for mono + Jmp MixModeCommon + +Mix0ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix0ModeSurround + + Mul Byte Ptr [SI+20h] ; Final volume + Add AX, 64 + ShR AX, 7 + Mov [SI+0Ch], AX ; Store into right volume + + Mov AL, 64 + Sub AL, [SI+37h] + Mul Byte Ptr [SI+20h] + Add AX, 64 + ShR AX, 7 + Mov [SI+0Eh], AX ; Left volume + + Mov CH, AL ; CH = left volume + Mov CL, [SI+0Ch] ; CL = right volume + Mov AX, 0 + + Test CX, CX + JZ MixModeCommon + + Mov AL, 30 ; Left only... + Test CL, CL + JZ MixModeCommon + + Mov AL, 60 + Test CH, CH + JZ MixModeCommon + + Mov AL, 90 + Cmp CL, CH + JZ MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix0ModeSurround: + Mov AL, [SI+20h] + ShR AL, 2 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 150 ; Surround + Jmp MixModeCommon + +Mix6ModeMono: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 8 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Test AX, AX + JZ MixModeCommon + Mov AX, 30 + Jmp MixModeCommon + +Mix6ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix6ModeSurround + + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Ch], AX ; Store into right volume + Mov BX, AX + ShL EAX, 16 + + Mov AL, 64 ; Do left volume + Sub AL, [SI+37h] ; AL = 64-FinalPan + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Eh], AX + + Mov ECX, EAX + + ; BX = right volume + ; CX = Left volume + Mov AX, 0 + Test ECX, ECX + JZ MixModeCommon + + Mov AL, 30 + Test BX, BX + JZ MixModeCommon + + Mov AL, 60 + Test CX, CX + JZ MixModeCommon + + Mov AL, 90 + Cmp CX, BX + JE MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix6ModeSurround: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 9 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + JZ MixModeCommon + Mov AX, 150 + Jmp MixModeCommon + +MixModeCommon: ; Requires AX = 30/60/90 etc. depending + ; On mixing mode type. + ; This will add 180 for 16-bit, + ; And sort out loop types. + Mov BL, [SI+0Ah] + Test Byte Ptr [SI+18h], 2 ; 16 bit? + JZ MixModeCommon1 + + Add AX, 180 + +MixModeCommon1: + Cmp BL, 8 + JB MixModeCommon3 ; No loop + JE MixModeCommon2 ; Forwards loop + + Add AX, 10 + +MixModeCommon2: + Add AX, 10 + +MixModeCommon3: + Add AX, Offset MixFunctionTables + Add AX, MixModeOffset + Mov [SI+8], AX ; Offset... + +MixSamplesMix: + Mov BX, [SI+8] ; BX = offset into + Mov EAX, [CS:BX+2] + Mov DWord Ptr PreMixFunction, EAX + Mov EAX, [CS:BX+6] + Mov DWord Ptr MixFunctionSeparateBackwards, EAX + + Mov AX, BytesToMix + Mov MixBlockSize, AX + Mov MixBufferOffset, MIXTABLESIZE + + Mov EAX, CURRENTPOSITION + Mov OLDPOSITION, EAX + + Call Word Ptr [CS:BX] + + And Word Ptr [SI], 0111100010001101b + Jmp MixSamplesEnd + +MixSamplesHandleError: + Mov Word Ptr [SI], 200h + + Test Byte Ptr [SI+3Ah], 80h + JNZ MixSamplesEnd + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Turn off channel + +MixSamplesEnd: + Pop CX + +MixSamplesEnd2: + Add SI, 128 + Dec CX + JNZ MixSamples2 + + Ret + +EndP MixSamples + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ESSIRQHandler + + PushAD + Push DS + Push ES + + ClD + + Mov AX, CS + Mov DS, AX + Assume DS:Driver + + Mov DX, [BasePort] + Inc Debug + + Inc DX + In AL, DX + Mov AH, AL + Xor AL, AL + Out DX, AL +; Call AD1816Out + + Mov AL, 20h + Cmp IRQ, 8 + JB WSSAckIRQ1 + + Out 0A0h, AL + +WSSAckIRQ1: + Out 20h, AL + + Mov AX, MixBufferPos + Mov BX, AX + Mul DMASize + Cmp AX, DMABUFFERLENGTH + JB ESSIRQHandler2 + + Xor AX, AX + Xor BX, BX + +ESSIRQHandler2: + Inc BX + Mov MixBufferPos, BX + + CLD + + + ; OK... time to get next block + ; Check whether stereo thing is on.. + ; + LES DI, [ActualDMAPtr] + Add DI, AX + + Mov BX, DMASize ; BX = bytes required + ShR BX, 1 + ; BX = samples required + Mov BP, 8 ; Skip for mono + Mov CL, 14 ; Shift for mono + + Cmp Stereo, 0 + JE ESSIRQHandlerMono + + Mov BP, 4 ; Stereo skip value. + Dec CL + +ESSIRQHandlerMono: + Call SaveEMSPageFrame + + Cmp MixTransferRemaining, 0 + JNE ESSIRQHandler4 + Assume DS:Nothing + +ESSIRQHandler3: + Push BX + Push CX + Push BP + Push ES + Push DI + + Call Update + Call MixSamples + + Pop DI + Pop ES + Pop BP + Pop CX + Pop BX + +ESSIRQHandler4: + Mov DS, MixSegment + Mov SI, MixTransferOffset + Mov DX, BX ; DX = samples to transfer + Cmp DX, MixTransferRemaining + JBE ESSIRQHandler5 + + Mov DX, MixTransferRemaining + +ESSIRQHandler5: + Push DX + Cmp CS:Filter, 1 + JB ESSIRQHandler6 + JE ESSIRQHFilter + + Cmp CS:Stereo, 0 + JE ESSIRQ3QFilterMono + +ESSIRQ3QFilterStereo: + Push BX + + Mov EBX, FilterValue + Mov EBP, FilterValue2 + ShR DX, 1 + +ESSIRQ3QFilterStereo1: + Mov EAX, EBX + Mov ECX, EBP + Add EAX, [SI] + Add ECX, [SI+4] + SAR EAX, 1 + SAR ECX, 1 + Add EBX, EAX + Add EBP, ECX + SAR EBX, 1 + SAR EBP, 1 + + Mov EAX, EBX + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSS3QFilterStereoClip1 + Cmp EAX, 7FFFh + JG WSS3QFilterStereoClip2 + +ESSIRQ3QFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSS3QFilterStereoClip3 + Cmp EAX, 7FFFh + JG WSS3QFilterStereoClip4 + +ESSIRQ3QFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ ESSIRQ3QFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp WSSMixTransferEnd + +ESSIRQ3QFilterMono: + Push BX + + Mov EBX, FilterValue + +ESSIRQ3QFilterMono1: + Mov EAX, EBX + Add EAX, [SI] + SAR EAX, 1 + Add EBX, EAX + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL WSS3QFilterMonoClip1 + Cmp EAX, 7FFFh + JG WSS3QFilterMonoClip2 + +ESSIRQ3QFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ ESSIRQ3QFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp WSSMixTransferEnd + +ESSIRQHFilter: + Cmp CS:Stereo, 0 + JE ESSIRQHFilterMono + +ESSIRQHFilterStereo: + Push BX + + Mov EBX, FilterValue + Mov EBP, FilterValue2 + ShR DX, 1 + +ESSIRQHFilterStereo1: + Add EBX, [SI] + Add EBP, [SI+4] + + SAR EBX, 1 + SAR EBP, 1 + + Mov EAX, EBX + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSSHFilterStereoClip1 + Cmp EAX, 7FFFh + JG WSSHFilterStereoClip2 + +ESSIRQHFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSSHFilterStereoClip3 + Cmp EAX, 7FFFh + JG WSSHFilterStereoClip4 + +ESSIRQHFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ ESSIRQHFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp WSSMixTransferEnd + +ESSIRQHFilterMono: + Push BX + + Mov EBX, FilterValue + +ESSIRQHFilterMono1: + Add EBX, [SI] + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL WSSHFilterMonoClip1 + Cmp EAX, 7FFFh + JG WSSHFilterMonoClip2 + +ESSIRQHFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ ESSIRQHFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp WSSMixTransferEnd + +ESSIRQHandler6: + Mov EAX, [SI] + SAR EAX, CL + + Cmp EAX, -8000h + JL ESSIRQHandlerClip1 + Cmp EAX, 7FFFh + JG ESSIRQHandlerClip2 + +ESSIRQHandler7: + StosW ; } Memory write + + Add SI, BP + Dec DX + JNZ ESSIRQHandler6 + +WSSMixTransferEnd: + Pop DX + + Sub MixTransferRemaining, DX ; } Memory write + Sub BX, DX + JNZ ESSIRQHandler3 + + Mov MixTransferOffset, SI ; } Memory write + + Call RestoreEMSPageFrame + + Pop ES + Pop DS + PopAD + IRet + +ESSIRQHandlerClip1: + Mov AX, 8000h + Jmp ESSIRQHandler7 + +ESSIRQHandlerClip2: + Mov AX, 7FFFh + Jmp ESSIRQHandler7 + +WSSHFilterMonoClip1: + Mov AX, 8000h + Jmp ESSIRQHFilterMono2 + +WSSHFilterMonoClip2: + Mov AX, 7FFFh + Jmp ESSIRQHFilterMono2 + +WSSHFilterStereoClip1: + Mov AX, 8000h + Jmp ESSIRQHFilterStereo2 + +WSSHFilterStereoClip2: + Mov AX, 7FFFh + Jmp ESSIRQHFilterStereo2 + +WSSHFilterStereoClip3: + Mov AX, 8000h + Jmp ESSIRQHFilterStereo3 + +WSSHFilterStereoClip4: + Mov AX, 7FFFh + Jmp ESSIRQHFilterStereo3 + +WSS3QFilterMonoClip1: + Mov AX, 8000h + Jmp ESSIRQ3QFilterMono2 + +WSS3QFilterMonoClip2: + Mov AX, 7FFFh + Jmp ESSIRQ3QFilterMono2 + +WSS3QFilterStereoClip1: + Mov AX, 8000h + Jmp ESSIRQ3QFilterStereo2 + +WSS3QFilterStereoClip2: + Mov AX, 7FFFh + Jmp ESSIRQ3QFilterStereo2 + +WSS3QFilterStereoClip3: + Mov AX, 8000h + Jmp ESSIRQ3QFilterStereo3 + +WSS3QFilterStereoClip4: + Mov AX, 7FFFh + Jmp ESSIRQ3QFilterStereo3 + +EndP ESSIRQHandler + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Add DI, Offset IRQData + Mov BX, [CS:DI] + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset ESSIRQHandler + + XChg [ES:BX], EAX + Mov OldESSIRQHandler, EAX + + Mov AX, IMR + And AX, [DI+2] + + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Pop ES + PopAD + + Ret + +EndP SetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Mov BX, [IRQData+DI] + + Mov EAX, OldESSIRQHandler + Mov [ES:BX], EAX + + Pop ES + PopAD + + Ret + +EndP ResetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StopAD1816 + + PushA + + Mov AL, 1 + Call AD1816RegisterIn + And BX, 07FFFh ; Disable PIE + Call AD1816RegisterOut + + Mov DX, CS:BasePort + Inc DX + In AL, DX + And AL, Not 80h + Out DX, AL + + Add DL, 7 + In AL, DX + And AL, Not 1 + Out DX, AL + + PopA + Ret + +EndP StopAD1816 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StartAD1816 + + PushA + Push ES + Push DS + + Push CS + Pop DS + Assume DS:Driver + + ; Setup DMA + Mov BX, DMASegment + Xor AX, AX + Mov DX, DMA + Mov DI, DMABUFFERLENGTH + Call SetDMA + + LES DI, ActualDMAPtr + Xor AX, AX + Mov CX, DMABUFFERLENGTH/2 + Rep StosW + + Mov MixBufferPos, 0 + Mov MixTransferRemaining, 0 + + Mov AL, 4 + Call AD1816RegisterIn + + Mov AL, 32 + Call AD1816RegisterIn + Or BX, 08000h + Call AD1816RegisterOut + + Mov AL, 2 ; Sample rate + Mov BX, MixSpeed + Call AD1816RegisterOut + + Mov AL, 8 ; DMA Size + Mov BX, DMASize + ShR BX, 2 + Dec BX + Call AD1816RegisterOut + + Mov DX, BasePort ; Wave Format + Add DL, 8 + + Mov AL, 00010001b + Cmp Stereo, 0 + JE StartAD1816A + + Or AL, 4 + +StartAD1816A: + Out DX, AL + + Mov AL, 1 ; Enable Playback interrupt + Call AD1816RegisterIn + Or BX, 8000h + Call AD1816RegisterOut + + Pop DS + Pop ES + PopA + + Ret + +EndP StartAD1816 + Assume DS:Nothing + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov SI, Offset RelocationTable + +RelocationFix: + LodsW + Test AX, AX + JZ RelocationEnd + Mov BX, AX + Mov [BX], DS + Jmp RelocationFix + + +RelocationEnd: + Call GetEMSPageFrame + Mov EMSPageFrame, AX + + In AL, 0A1h + Mov AH, AL + In AL, 21h + Mov IMR, AX + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + Mov AX, MixSpeed + Cmp AX, 11050 + JA ClipMixSpeed1 + + Mov MixSpeed, 11050 + +ClipMixSpeed1: + Cmp AX, 55200 + JB ClipMixSpeed2 + + Mov MixSpeed, 55200 + +ClipMixSpeed2: + Mov AX, 2643 + Mul MixSpeed + Add AX, 0FFFFh + AdC DX, 2080 + + Mov BX, (DMABUFFERLENGTH*2)/16 + Add BX, DX + + ; Allocate MixSegment first + Mov AH, 48h + + Int 21h + JNC InitSound1 + +InitSoundNoMemory: + Mov SI, Offset ESSNoMemoryMsg + Ret + +InitSound1: + Mov MixSegment, AX + Add AX, DX + Mov DMASegment, AX + + Call SetIRQ + Call GetTempo + Call SetTempo + + Call UpdateSoundcardVariables + + Mov DI, 1 + Call SetSAM9407 + + Mov SI, Offset ESSMsg + + Mov AX, BasePort + Mov BX, IRQ + Mov CX, DMA + + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Call ResetIRQ + Call SetIRQ + + Mov SI, Offset ReInitMsg + Mov BX, 40 + Call SetInfoLine + + Mov AL, Stereo + Call SetStereo + + Pop ES + Pop DS + PopA + + Ret + +EndP ReInitSound + Assume DS:Nothing + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, IMR + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Mov AX, MixSegment + Test AX, AX + JZ UnInitSound1 + + Push AX + + Call StopAD1816 + Call ResetIRQ + + Pop ES + Mov AH, 49h ; Release MixSegment + Int 21h + + +UnInitSound1: + Call GotoHomeDirectory + + ; Now to save config into driver file. + Mov AX, 3D02h ; Read write access + Mov DX, Offset DriverName + Int 21h + JC SetMixMode1 + + Mov BX, AX + + Mov AX, 4200h + Xor CX, CX + Mov DX, Offset CONFIGURATIONOFFSET + Int 21h + JC SetMixMode2 + + Mov AH, 40h + Mov CX, CONFIGSIZE + Mov DX, Offset MixMode + Int 21h + +SetMixMode2: + Mov AH, 3Eh + Int 21h + +SetMixMode1: + Ret + +EndP UnInitSound + Assume DS:Nothing + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + +DMAPort1 EQU $+1 + In AL, 1 + Mov BL, AL + +DMAPort2 EQU $+1 + In AL, 1 + Mov BH, AL + + Mov CS:Debug2, BX + + Ret + +EndP Poll + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Push AX + Push BX + Push DX + + Push BX + + Mov AX, MixSpeed + Mov BX, AX + Xor DX, DX + + ShL AX, 1 + RCL DX, 1 ; DX:AX = Mixspeed*2 + + ShR BX, 1 ; BX = Mixspeed/2 + + Add AX, BX + AdC DX, 0 ; DX:AX = Mixspeed*2.5 + + Pop BX ; BX = tempo + Div BX + + Mov BytesToMix, AX + + Pop DX + Pop BX + Pop AX + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + PushA + Push DS + + Mov BX, AX ; BX = MixVolume + Mov CS:MixVolume, BX + + Mov AX, CS:MixSegment + Test AX, AX + JZ SetMixVolume2 + + Mov DS, AX + + Mov CX, MIXTABLESIZE/2 + Mov SI, MIXTABLESIZE-2; Starting point - working backwards + +SetMixVolume1: + Mov AX, CX + + Dec AX ; AH = volume, AL = wave value. + Xor DX, DX + XChg AH, DL ; DL = Volume, AX = wave value + CBW + + IMul DX ; DX:AX = Volume * Wave Value + ; Ranges -8192->8128 + + IMul BX ; DX:AX = Volume * Wave Value * Mixing Volume + ; Ranges -1048576->1040384 + + Add AX, 64 + AdC DX, 0 + + ShRD AX, DX, 7 + Mov [SI], AX + Sub SI, 2 + + Loop SetMixVolume1 + +SetMixVolume2: + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS:RecalculateAllVolumes + + Pop DS + PopA + + Ret + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Mov CS:Stereo, AL + Cmp CS:MixSegment, 0 + JE SetStereo1 + + Push AX + + Call StopAD1816 + Call StartAD1816 + + Pop DI + And DI, 1 + Add DI, 31 + Call SetSAM9407 + + Mov DI, 2 +SetStereo2: + Call SetSAM9407 + Inc DI + Cmp DI, 30 + JBE SetStereo2 + +SetStereo1: + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include loadsam.inc + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset WSSScreenList + + ClC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far + + Xor AH, AH + Mov AL, [CS:VolumeTable+DI] + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UpdateSoundcardVariables + + Mov AL, 4 + Mov BX, 3F3Fh + Sub BX, [Word Ptr CS:VolumeTable] + Call AD1816RegisterOut + + Mov AL, 33 + Mov BX, 40h + Call AD1816RegisterOut + + Mov AL, 14 + Xor BX, BX + Call AD1816RegisterOut + + Mov AL, 44 + Xor BX, BX + Call AD1816RegisterOut + + Ret + +EndP UpdateSoundcardVariables + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far + + Mov [CS:VolumeTable+DI], AL + Cmp DI, 31 + JAE SetVariable1 + Cmp DI, 2 + JB SetVariable1 + + Call SetSAM9407 + Ret + +SetVariable1: + Call UpdateSoundcardVariables + Ret + +EndP SetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. + +StopAfterPlay DW 0 +DefaultChannels DW 64 + DW 5 Dup (0) + + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/TEST.ASM b/SoundDrivers/TEST.ASM new file mode 100755 index 0000000..ea4a7ed --- /dev/null +++ b/SoundDrivers/TEST.ASM @@ -0,0 +1,306 @@ + + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +; ÄÄ Variables ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +TestDriverMsg DB "Test Driver", 13 + DB "(No sound output)", 0 +TestReinitMsg DB "Test driver: Reinitialise received", 0 +Filler DB 8039 Dup (0) + +; ÄÄ EmptyFunction ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc EmptyFunction Far + + Xor AX, AX + StC + Ret + +EndP EmptyFunction + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far + + Mov EAX, 'Jeff' + ClC + Ret + +EndP DetectCard + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + + Mov SI, Offset TestDriverMsg + + ClC + Ret + +EndP InitSound + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + Push CS + Pop DS + Mov SI, Offset TestReinitMsg + Mov BX, 200 + Call SetInfoLine + + Ret + +EndP ReInitSound + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Ret + +EndP UnInitSound + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + Call SaveEMSPageFrame + Call Update + Call RestoreEMSPageFrame + + Ret + +EndP Poll + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + Ret + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc LoadSample Far + + StC + Ret + +EndP LoadSample + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Xor AX, AX + StC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far + + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far + + Ret + +EndP SetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. + DW 0 ; Stop after play flag. +DefaultChannels DW 64 + DW 0 ; Flags, MIDI, Hiqual, Waveform + DW 4 Dup (0) + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/VSND.ASM b/SoundDrivers/VSND.ASM new file mode 100755 index 0000000..50a21b0 --- /dev/null +++ b/SoundDrivers/VSND.ASM @@ -0,0 +1,1281 @@ +; +; Impulse Tracker VSound Driver +; +; Client for VSound.VxD to interface with Windows. +; Output is always 16-bit stereo, 44100Hz. +; +; + +STEREOENABLED EQU 1 +MIXRESOLUTION EQU 32 ; 32 bit mixing +OUTPUTFILTERENABLED EQU 0 +TIMERCONST EQU 11932 ; 100 times a second +MIXTABLESIZE EQU 2*256*65 +DMABUFFERLENGTH EQU 0 ; Does not have a DMA buffer in the mixsegment + + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +; ÄÄ Variables ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +OldTimerIRQHandler DD 0 +TimerAccumulator DW 0 + +VSoundNoMemoryMsg DB "Impulse Tracker VSound Driver", 13 + DB "Error: Insufficient memory", 0 +VSoundDriverMsg DB "Impulse Tracker VSound Driver", 0 + +NoReinitMsg DB "VSound driver should NOT require reinitialisation ", 0 + +VSoundIDBuffer DB 8 Dup (0) +VSoundID DB "ITVXDDRV" + +DefaultDriverName DB "ITVSOUND.DRV" +DriverName DD 0 + +Forced DB 0 +Stereo DB 0 +MixVolume DW 0 +MixSegment DW 0 + +BytesToMix DW 1000 +MixTransferOffset DW 0 +MixTransferRemaining DW 0 +CONFIGURATIONOFFSET EQU $+128 +CONFIGSIZE EQU 4 +MixMode DW 0 +MixModeOffset DW 0 + +VSoundScreenList Label + DW 6 + DW Near Ptr IdleFunctionList + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr VSoundHeaderLine + + DW Near Ptr DriverText + + DW Near Ptr MixModeText + DW Near Ptr MixModeButton1 ; 6 + DW Near Ptr MixModeButton2 ; + DW Near Ptr MixModeButton3 ; 8 + DW Near Ptr MixModeButton4 ; 9 + + DW Near Ptr ServerText + DW Near Ptr FrequencyText + + DW 0 + + +VSoundHeaderLine DW 10 + DB "Virtual Sound Driver", 0 + +ServerText DW 1 + DB 2, 47 + DB 21h +VSoundString DB 64 Dup (0) + +FrequencyText DW 1 + DB 2, 48 + DB 21h + DB "Playback Frequency: ", 0FDh, "DHz, Buffer Threshold: ", 0FDh, "D bytes", 0 +Threshold DW 21*1024 +MixSpeed DW 44100 + DW 0 + +DriverText DW 1 + DB 2, 46 + DB 21h + DB "Virtual Sound Driver 1.0 for Impulse Tracker", 0 + +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +IdleFunctionList DD 0 + DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +MixModeText DW 1 + DB 2, 14 + DB 20h + DB "Mixing Mode", 0 + +MixModeButton1 DW 2 + DW 0FFFFh, 7, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment1 DW 0 + DW 0 + DW Offset SetMixMode +DriverSegment2 DW 0 + DB 3, 16, 32, 18, 8 + DB 0 + DB " 16 Bit, Non-Interpolated", 0 + +MixModeButton2 DW 2 + DW 6, 8, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment3 DW 0 + DW 2 + DW Offset SetMixMode +DriverSegment4 DW 0 + DB 3, 19, 32, 21, 8 + DB 0 + DB " 16 Bit, Interpolated", 0 + +MixModeButton3 DW 2 + DW 7, 9, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment5 DW 0 + DW 4 + DW Offset SetMixMode +DriverSegment6 DW 0 + DB 3, 22, 32, 24, 8 + DB 0 + DB " 32 Bit, Non-Interpolated", 0 + +MixModeButton4 DW 2 + DW 8, 0FFFFh, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment7 DW 0 + DW 6 + DW Offset SetMixMode +DriverSegment8 DW 0 + DB 3, 25, 32, 27, 8 + DB 0 + DB " 32 Bit, Interpolated", 0 + + +; ÄÄ MixingRoutines ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixBufferPos DW 0 + +include mix.inc +include m12bit.mix +include m12biti.mix +include m32bit.mix +include m32biti.mix + +ALIGN 2 + +MixFunctionTables Label + +include m12bit.inc ; contains the tables +include m12biti.inc +include m32bit.inc +include m32biti.inc + +include nodebug.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +RelocationTable Label Word + DW Offset DriverSegment1, Offset DriverSegment2 + DW Offset DriverSegment3, Offset DriverSegment4 + DW Offset DriverSegment5, Offset DriverSegment6 + DW Offset DriverSegment7, Offset DriverSegment8 + DW 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixMode Far + + Push CS + Pop ES + Mov DI, Offset MixMode + + Ret + +EndP GetMixMode + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixMode Far + + Mov AX, [SI+22] + + ClI + + Mov CS:MixMode, AX + + Mov BX, 180 + Mul BX + Mov CS:MixModeOffset, AX + + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS:RecalculateAllVolumes + + StI + + Mov AX, 1 + Ret + +EndP SetMixMode + Assume DS:Nothing + + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far + + Push CS + Push CS + Pop DS + Pop ES + Assume DS:Driver + + Mov Forced, AL + + Cmp BX, 217h + JAE DetectCardUseDriver + + Mov CX, DS + ShL ECX, 16 + Mov CX, Offset DefaultDriverName + +DetectCardUseDriver: + Mov DriverName, ECX + +; First need to find if VSound server is setup. + Mov DX, BasePort + Cmp DX, 0FFFFh + JNE PortSpecified + + Mov DX, 400h + Jmp TestPort + +PortSpecified: + Cmp AL, 1 + JNE DetectCardError + + +TestPort: + Mov BasePort, DX + + Xor AL, AL + Out DX, AL ; Reset, get identification + + Mov CX, 8 + Mov DI, Offset VSoundIDBuffer + Rep InsB + + Mov SI, Offset VSoundIDBuffer ; DI now points to VSoundID + Mov CX, 8 + RepE CmpsB + JNE DetectCardError + +; We've found a VSound server. Get ServerString + + Mov AL, 1 + Out DX, AL + ; DI now points to ServerString. + Mov DI, Offset VSoundString + Mov CX, 60 + Rep InsB + + Mov DI, Offset Threshold + Mov CX, 4 + Rep InsB + + Xor DWord Ptr [Threshold], 0FFFFFFFFh + + Mov EAX, 'Jeff' + DB 85h + +DetectCardError: + StC + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +InVSound DB -1 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixModeTable Label Word + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + +Proc MixSamples ; Given DS:SI = info tables, CX = numchannels + + ; 1. Clean buffer + ; + update variables + ; 2. Update parameters + ; 3. Mix func + ; 4. Return + + Push CX + + Mov CX, BytesToMix + Mov ES, MixSegment + Mov DI, MIXTABLESIZE + Xor EAX, EAX + Mov DX, CX + Add CX, CX + + Mov MixTransferOffset, DI ; } Memory write + + Cmp Stereo, 0 + JE MixSamples1 + + Mov DX, CX + +MixSamples1: + Rep StosD ; } Memory write + Mov MixTransferRemaining, DX ; } + + Pop CX + +MixSamples2: + Test Byte Ptr [SI], 1 + JZ MixSamplesEnd2 + Cmp Byte Ptr [SI+36h], 100 + JE MixSamplesEnd2 + + Push CX + Mov CX, [SI] + + Test CH, 2 + JZ MixSamples3 + And Byte Ptr [SI], Not 1 + + Jmp MixSamplesEnd +; Cmp MixMode, 8 ; Is it volume ramping? +; JB MixSamplesEnd + +MixSamples3: + Test CL, 20h ; New freq? + JZ MixSamples5 + + Mov AX, [SI+10h] + Mov DX, [SI+12h] + Mov BX, MixSpeed + Cmp DX, BX + JAE MixSamplesHandleError + + Div BX + ShL EAX, 16 + Xor AX, AX + Div BX + Mov STEPVALUE, EAX + +MixSamples4: + Test CH, 1 + JZ MixSamples5 + + Mov DWord Ptr [SI+1Ch], 0 ; Current Volume = 0 + ; for volume sliding. +MixSamples5: + Test CX, 8440h ; New volume or panning? + JZ MixSamplesMix + + Xor AX, AX + Test CH, 8 ; Muted? + JNZ MixModeCommon + + Mov BX, MixMode + Add BL, Stereo + Add BX, BX + Jmp [CS:MixModeTable+BX] + +Mix0Mode: ; 16-bit mixing, no interpolation +Mix0ModeMono: ; and 16-bit mixing, interpolation + Mov AL, [SI+20h] + ShR AL, 1 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 30 ; Use left only-mixing for mono + Jmp MixModeCommon + +Mix0ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix0ModeSurround + + Mul Byte Ptr [SI+20h] ; Final volume + Add AX, 64 + ShR AX, 7 + Mov [SI+0Ch], AX ; Store into right volume + + Mov AL, 64 + Sub AL, [SI+37h] + Mul Byte Ptr [SI+20h] + Add AX, 64 + ShR AX, 7 + Mov [SI+0Eh], AX ; Left volume + + Mov CH, AL ; CH = left volume + Mov CL, [SI+0Ch] ; CL = right volume + Mov AX, 0 + + Test CX, CX + JZ MixModeCommon + + Mov AL, 30 ; Left only... + Test CL, CL + JZ MixModeCommon + + Mov AL, 60 + Test CH, CH + JZ MixModeCommon + + Mov AL, 90 + Cmp CL, CH + JZ MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix0ModeSurround: + Mov AL, [SI+20h] + ShR AL, 2 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 150 ; Surround + Jmp MixModeCommon + +Mix6ModeMono: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 8 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Test AX, AX + JZ MixModeCommon + Mov AX, 30 + Jmp MixModeCommon + +Mix6ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix6ModeSurround + + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Ch], AX ; Store into right volume + Mov BX, AX + ShL EAX, 16 + + Mov AL, 64 ; Do left volume + Sub AL, [SI+37h] ; AL = 64-FinalPan + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Eh], AX + + Mov ECX, EAX + + ; BX = right volume + ; CX = Left volume + Mov AX, 0 + Test ECX, ECX + JZ MixModeCommon + + Mov AL, 30 + Test BX, BX + JZ MixModeCommon + + Mov AL, 60 + Test CX, CX + JZ MixModeCommon + + Mov AL, 90 + Cmp CX, BX + JE MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix6ModeSurround: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 9 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + JZ MixModeCommon + Mov AX, 150 + Jmp MixModeCommon + +MixModeCommon: ; Requires AX = 30/60/90 etc. depending + ; On mixing mode type. + ; This will add 180 for 16-bit, + ; And sort out loop types. + Mov BL, [SI+0Ah] + Test Byte Ptr [SI+18h], 2 ; 16 bit? + JZ MixModeCommon1 + + Add AX, 180 + +MixModeCommon1: + Cmp BL, 8 + JB MixModeCommon3 ; No loop + JE MixModeCommon2 ; Forwards loop + + Add AX, 10 + +MixModeCommon2: + Add AX, 10 + +MixModeCommon3: + Add AX, Offset MixFunctionTables + Add AX, MixModeOffset + Mov [SI+8], AX ; Offset... + +MixSamplesMix: + Mov BX, [SI+8] ; BX = offset into + Mov EAX, [CS:BX+2] + Mov DWord Ptr PreMixFunction, EAX + Mov EAX, [CS:BX+6] + Mov DWord Ptr MixFunctionSeparateBackwards, EAX + + Mov AX, BytesToMix + Mov MixBlockSize, AX + Mov MixBufferOffset, MIXTABLESIZE + + Mov EAX, CURRENTPOSITION + Mov OLDPOSITION, EAX + + Call Word Ptr [CS:BX] + + And Word Ptr [SI], 0111100010001101b + Jmp MixSamplesEnd + +MixSamplesHandleError: + Mov Word Ptr [SI], 200h + + Test Byte Ptr [SI+3Ah], 80h + JNZ MixSamplesEnd + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Turn off channel + +MixSamplesEnd: + Pop CX + +MixSamplesEnd2: + Add SI, 128 + Dec CX + JNZ MixSamples2 + + Ret + +EndP MixSamples + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc VSoundFillBuffer + Assume DS:Nothing + +VSoundHandler3: + + Mov DX, BasePort + Mov AL, 2 + Out DX, AL + In AL, DX + Mov AH, AL + In AL, DX ; AX = BufferSize + + Cmp AX, Threshold + JB VSoundHandler4 + + Ret + +VSoundHandler4: + Call Update + Call MixSamples + +; Convert the buffer + Mov DS, MixSegment + Mov SI, MixTransferOffset + Mov CX, BytesToMix ; CX = number of 32-bit samples to mix. + Mov DI, SI + +; Transfer the buffer + Cmp Stereo, 0 + JE VSoundHandlerMono + +VSoundHandlerStereo: + Mov EAX, [SI] + Mov EBX, [SI+4] + + SAR EAX, 13 + SAR EBX, 13 + + Cmp EAX, -8000h + JL VSoundHandlerStereoClip1 + Cmp EAX, 7FFFh + JG VSoundHandlerStereoClip2 + +VSoundHandlerStereo1: + Cmp EBX, -8000h + JL VSoundHandlerStereoClip3 + Cmp EBX, 7FFFh + JG VSoundHandlerStereoClip4 + +VSoundHandlerStereo2: + Mov [DI], AX + Add SI, 8 + Mov [DI+2], BX + Add DI, 4 + + Loop VSoundHandlerStereo + Jmp VSoundHandlerSend + +VSoundHandlerMono: + Mov EAX, [SI] + SAR EAX, 14 + + Cmp EAX, -8000h + JL VSoundHandlerMonoClip1 + Cmp EAX, 7FFFh + JG VSoundHandlerMonoClip2 + +VSoundHandlerMono1: + Mov [DI], AX + Add SI, 8 + Mov [DI+2], AX + Add DI, 4 + + Loop VSoundHandlerMono + +VSoundHandlerSend: + Mov CX, BytesToMix + Mov DX, BasePort + ShL CX, 2 + Add DX, 2 + Mov SI, MixTransferOffset + Rep OutsB + + Jmp VSoundHandler3 + +VSoundHandlerStereoClip1: + Mov AX, 8000h + Jmp VSoundHandlerStereo1 + +VSoundHandlerStereoClip2: + Mov AX, 7FFFh + Jmp VSoundHandlerStereo1 + +VSoundHandlerStereoClip3: + Mov BX, 8000h + Jmp VSoundHandlerStereo2 + +VSoundHandlerStereoClip4: + Mov BX, 7FFFh + Jmp VSoundHandlerStereo2 + + +VSoundHandlerMonoClip1: + Mov AX, 8000h + Jmp VSoundHandlerMono1 + +VSoundHandlerMonoClip2: + Mov AX, 7FFFh + Jmp VSoundHandlerMono1 + + +EndP VSoundFillBuffer + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc VSoundHandler + + PushAD + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Add TimerAccumulator, TIMERCONST + JC VSoundHandler1 + + Mov AL, 20h + Out 20h, AL + Jmp VSoundHandler2 + +VSoundHandler1: + PushF + Call [OldTimerIRQHandler] + +VSoundHandler2: + Add InVSound, 1 + JNC VSoundExit + + Call SaveEMSPageFrame + + Assume DS:Nothing + Call VSoundFillBuffer + + Call RestoreEMSPageFrame + +VSoundExit: + Pop ES + Pop DS + PopAD + + Sub CS:InVSound, 1 + IRet + +EndP VSoundHandler + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov AL, 34h ; Program IRQ 0. LSB&MSB, Rate gen + Out 43h, AL ; bump the interrupt to be called + ; 100 times a second. + Mov AX, TIMERCONST + Out 40h, AL + Mov AL, AH + Out 40h, AL + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset VSoundHandler + + ClI + + XChg [ES:20h], EAX ; Hook to timer interrupt + Mov CS:OldTimerIRQHandler, EAX + + StI + + Pop ES + PopAD + + Ret + +EndP SetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov AL, 34h ; Program IRQ 0. LSB&MSB, Rate gen + Out 43h, AL + + Xor AL, AL + Out 40h, AL ; Interrupt called at normal 18.2 times + Out 40h, AL + + Mov EAX, CS:OldTimerIRQHandler + Mov [ES:20h], EAX + + Pop ES + PopAD + + Ret + +EndP ResetIRQ + Assume DS:Nothing + + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov SI, Offset RelocationTable + +RelocationFix: + LodsW + Test AX, AX + JZ RelocationEnd + Mov BX, AX + Mov [BX], DS + Jmp RelocationFix + + +RelocationEnd: + Call GetEMSPageFrame + Mov EMSPageFrame, AX + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + ; Parags to allocate = (8/(.4*31*16))*MixSpeed + 2080 + ; = .04032258*MixSpeed = (65536*.04032258*MixSpeed) / 65536 + 2080 + + Mov AX, 2643 + Mul MixSpeed + Add AX, 0FFFFh + AdC DX, 2080 + Mov BX, DX + Mov AH, 48h + Int 21h + + Mov SI, Offset VSoundNoMemoryMsg + JNC InitSound1 + + Pop ES + Ret + +InitSound1: + Mov MixSegment, AX + + Call SetIRQ + Call GetTempo + Call SetTempo + + Mov SI, Offset VSoundDriverMsg + Mov AX, BasePort + + ClC + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + Push CS + Pop DS + + Mov SI, Offset NoReinitMsg + Mov BX, 40 + Call SetInfoLine + + Ret + +EndP ReInitSound + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Call GotoHomeDirectory + + Mov DS, Word Ptr [CS:DriverName+2] + Mov DX, Word Ptr [CS:DriverName] + + Mov AX, 3D02h ; Read write access + Int 21h + + Push CS + Pop DS + Assume DS:Driver + + JC SaveConfig2 + + Mov BX, AX + + Mov AX, 4200h + Xor CX, CX + Mov DX, Offset CONFIGURATIONOFFSET + Int 21h + JC SaveConfig1 + + Mov AH, 40h + Mov CX, CONFIGSIZE + Mov DX, Offset MixMode + Int 21h + +SaveConfig1: + Mov AH, 3Eh + Int 21h + +SaveConfig2: + Mov AX, MixSegment + Test AX, AX + JZ UnInitSound1 + + Mov ES, AX + Mov AH, 49h ; Release MixSegment + Int 21h + + Call ResetIRQ + +UnInitSound1: + Mov DX, BasePort + Mov AL, 3 + Out DX, AL + + Ret + +EndP UnInitSound + Assume DS:Nothing + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + ClI + Add CS:InVSound, 1 + JNC Poll1 + + Call VSoundFillBuffer + +Poll1: + Sub CS:InVSound, 1 + StI + + Ret + +EndP Poll + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + Assume DS:Nothing + + Push AX + Push BX + Push DX + + Push BX + + Mov AX, MixSpeed + Mov BX, AX + Xor DX, DX + + ShL AX, 1 + RCL DX, 1 ; DX:AX = Mixspeed*2 + + ShR BX, 1 ; BX = Mixspeed/2 + + Add AX, BX + AdC DX, 0 ; DX:AX = Mixspeed*2.5 + + Pop BX ; BX = tempo + Div BX + + Mov BytesToMix, AX + + Pop DX + Pop BX + Pop AX + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + PushA + Push DS + + Mov BX, AX ; BX = MixVolume + Mov CS:MixVolume, AX + + Mov AX, CS:MixSegment + Test AX, AX + JZ SetMixVolume2 + + Mov DS, AX + + Mov CX, MIXTABLESIZE/2 + Mov SI, MIXTABLESIZE-2; Starting point - working backwards + +SetMixVolume1: + Mov AX, CX + + Dec AX ; AH = volume, AL = wave value. + Xor DX, DX + XChg AH, DL ; DL = Volume, AX = wave value + CBW + + IMul DX ; DX:AX = Volume * Wave Value + ; Ranges -8192->8128 + + IMul BX ; DX:AX = Volume * Wave Value * Mixing Volume + ; Ranges -1048576->1040384 + + Add AX, 64 + AdC DX, 0 + + ShRD AX, DX, 7 + Mov [SI], AX + Sub SI, 2 + + Dec CX + JNZ SetMixVolume1 + +SetMixVolume2: + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS: RecalculateAllVolumes + + Pop DS + PopA + + Ret + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Mov CS:Stereo, AL + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include loadsam.inc + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset VSoundScreenList + + ClC + + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far + + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far + + Ret + +EndP SetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. + DW 0 +DefaultChannels DW 128 + DW 0 + DW 4 Dup (0) + + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/VSNDMMX.ASM b/SoundDrivers/VSNDMMX.ASM new file mode 100755 index 0000000..bf3c966 --- /dev/null +++ b/SoundDrivers/VSNDMMX.ASM @@ -0,0 +1,1097 @@ +; +; Impulse Tracker VSound Driver +; +; Client for VSound.VxD to interface with Windows. +; Output is always 16-bit stereo, 44100Hz. +; +; + +STEREOENABLED EQU 1 +MIXRESOLUTION EQU 32 ; 32 bit mixing +OUTPUTFILTERENABLED EQU 0 +TIMERCONST EQU 11932 ; 100 times a second +DMABUFFERLENGTH EQU 0 ; Does not have a DMA buffer in the mixsegment + + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +; ÄÄ Variables ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +FPSave DB 128 Dup (0) + +OldTimerIRQHandler DD 0 +TimerAccumulator DW 0 + +VSoundNoMemoryMsg DB "Impulse Tracker VSound Driver", 13 + DB "Error: Insufficient memory", 0 +VSoundDriverMsg DB "Impulse Tracker VSound Driver", 13 + DB "MMX Accelerated Mixing Engine", 0 + +NoReinitMsg DB "VSound driver should NOT require reinitialisation ", 0 + +VSoundIDBuffer DB 8 Dup (0) +VSoundID DB "ITVXDDRV" + +DefaultDriverName DB "ITVSOUND.DRV" +DriverName DD 0 + +Forced DB 0 +Stereo DB 0 +MixVolume DW 0 +MixSegment DW 0 + +BytesToMix DW 1000 +MixTransferOffset DW 0 +MixTransferRemaining DW 0 +CONFIGURATIONOFFSET EQU $+128 +CONFIGSIZE EQU 4 +MixMode DW 0 +MixModeOffset DW 0 + +VSoundScreenList Label + DW 6 + DW Near Ptr IdleFunctionList + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr VSoundHeaderLine + + DW Near Ptr DriverText + + DW Near Ptr MixModeText + DW Near Ptr MixModeButton1 ; 6 + DW Near Ptr MixModeButton2 ; + DW Near Ptr MixModeButton3 ; 8 + DW Near Ptr MixModeButton4 ; 9 + + DW Near Ptr ServerText + DW Near Ptr FrequencyText + + DW 0 + + +VSoundHeaderLine DW 10 + DB "Virtual Sound Driver (MMX)", 0 + +ServerText DW 1 + DB 2, 47 + DB 21h +VSoundString DB 64 Dup (0) + +FrequencyText DW 1 + DB 2, 48 + DB 21h + DB "Playback Frequency: ", 0FDh, "DHz, Buffer Threshold: ", 0FDh, "D bytes", 0 +Threshold DW 21*1024 +MixSpeed DW 44100 + DW 0 + +DriverText DW 1 + DB 2, 46 + DB 21h + DB "Virtual Sound Driver (MMX) 1.0 for Impulse Tracker", 0 + +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +IdleFunctionList DD 0 + DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +MixModeText DW 1 + DB 2, 14 + DB 20h + DB "Mixing Mode", 0 + +MixModeButton1 DW 2 + DW 0FFFFh, 7, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment1 DW 0 + DW 0 + DW Offset SetMixMode +DriverSegment2 DW 0 + DB 3, 16, 32, 18, 8 + DB 0 + DB " MMX, Non-Interpolated", 0 + +MixModeButton2 DW 2 + DW 6, 8, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment3 DW 0 + DW 1 + DW Offset SetMixMode +DriverSegment4 DW 0 + DB 3, 19, 32, 21, 8 + DB 0 + DB " MMX, Interpolated", 0 + +MixModeButton3 DW 2 + DW 7, 9, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment5 DW 0 + DW 2 + DW Offset SetMixMode +DriverSegment6 DW 0 + DB 3, 22, 32, 24, 8 + DB 0 + DB " MMX, Volume Ramped", 0 + +MixModeButton4 DW 2 + DW 8, 0FFFFh, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment7 DW 0 + DW 3 + DW Offset SetMixMode +DriverSegment8 DW 0 + DB 3, 25, 32, 27, 8 + DB 0 + DB " MMX, Filtered", 0 + + +; ÄÄ MixingRoutines ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixBufferPos DW 0 + +include mix.inc +include mmx.inc + +include m32bitm.mix +include m32bitmi.mix +include m32bitmv.mix +include m32bitmf.mix + +ALIGN 2 + +MixFunctionTables Label + +include m32bitm.inc +include m32bitmi.inc +include m32bitmv.inc +include m32bitmf.inc +include mnomix.inc + +include nodebug.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +RelocationTable Label Word + DW Offset DriverSegment1, Offset DriverSegment2 + DW Offset DriverSegment3, Offset DriverSegment4 + DW Offset DriverSegment5, Offset DriverSegment6 + DW Offset DriverSegment7, Offset DriverSegment8 + DW 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixMode Far + + Push CS + Pop ES + Mov DI, Offset MixMode + + Ret + +EndP GetMixMode + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixMode Far + + Mov AX, [SI+22] + + ClI + + Mov CS:MixMode, AX + + Mov BX, 60 + Mul BX + Mov CS:MixModeOffset, AX + + StI + + Mov AX, 1 + Ret + +EndP SetMixMode + Assume DS:Nothing + + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectMMX + + Trace "Detecting MMX - CPUID Check" + + PushFD + Pop EAX + Mov EBX, EAX + Xor EAX, 00200000h + Push EAX + PopFD + PushFD + Pop EAX + Cmp EAX, EBX + JZ DetectMMXFail + + Trace "CPUID - Check OK" + + Mov EAX, 1 + DB 0Fh, 0A2h ; CPUID + Test EDX, 800000h + JZ DetectMMXFail + + Trace "MMX Detected" + + ClC + Ret + +DetectMMXFail: + Trace "MMX Not Detected" + + StC + Ret + +EndP DetectMMX + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far + + Push CS + Push CS + Pop DS + Pop ES + Assume DS:Driver + + Mov Forced, AL + + Cmp BX, 217h + JAE DetectCardUseDriver + + Mov CX, DS + ShL ECX, 16 + Mov CX, Offset DefaultDriverName + +DetectCardUseDriver: + Mov DriverName, ECX + + Call DetectMMX + JC DetectCardError + +; First need to find if VSound server is setup. + Mov DX, BasePort + Cmp DX, 0FFFFh + JNE PortSpecified + + Mov DX, 400h + Jmp TestPort + +PortSpecified: + Cmp AL, 1 + JNE DetectCardError + + +TestPort: + Mov BasePort, DX + + Xor AL, AL + Out DX, AL ; Reset, get identification + + Mov CX, 8 + Mov DI, Offset VSoundIDBuffer + Rep InsB + + Mov SI, Offset VSoundIDBuffer ; DI now points to VSoundID + Mov CX, 8 + RepE CmpsB + JNE DetectCardError + +; We've found a VSound server. Get ServerString + + Mov AL, 1 + Out DX, AL + ; DI now points to ServerString. + Mov DI, Offset VSoundString + Mov CX, 60 + Rep InsB + + Mov DI, Offset Threshold + Mov CX, 4 + Rep InsB + + Xor DWord Ptr [Threshold], 0FFFFFFFFh + + Mov EAX, 'Jeff' + DB 85h + +DetectCardError: + StC + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include mmxmsam.inc +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +InVSound DB -1 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc VSoundFillBuffer + Assume DS:Nothing + +VSoundHandler3: + + Mov DX, BasePort + Mov AL, 2 + Out DX, AL + In AL, DX + Mov AH, AL + In AL, DX ; AX = BufferSize + + Cmp AX, Threshold + JB VSoundHandler4 + + Ret + +VSoundHandler4: + Call Update + Call MixSamples + +; Convert the buffer + Mov DS, MixSegment + Mov SI, MixTransferOffset + Mov CX, BytesToMix ; CX = number of 32-bit samples to mix. + Mov DI, SI + +; Transfer the buffer + Cmp Stereo, 0 + JE VSoundHandlerMono + +VSoundHandlerStereo: + Add CX, 3 + ShR CX, 2 + +VsoundHandlerStereo1: + MovQ MM0, [SI] ; MM0 = s0r | s0l + MovQ MM1, [SI+8] ; MM1 = s1r | s1l + MovQ MM2, [SI+10h] ; MM2 = s2r | s2l + MovQ MM3, [SI+18h] ; MM3 = s3r | s3l + + PSRADI MM0, 12 + PSRADI MM1, 12 + PSRADI MM2, 12 + PSRADI MM3, 12 + + PackSSDW MM0, MM1 + PackSSDW MM2, MM3 + + MovQM [DI], MM0 + MovQM [DI+8], MM2 + + Add SI, 20h + Add DI, 10h + + Loop VSoundHandlerStereo1 + Jmp VSoundHandlerSend + +VSoundHandlerMono: + Inc CX + ShR CX, 1 + +VSoundHandlerMono1: +; want final to be s1|s1|s0|s0 (16 bits) +; Do 2 samples at a time. + MovD MM0, [SI] + MovD MM1, [SI+8] + MovD MM2, [SI+10h] + MovD MM3, [SI+18h] + + PUnpckLDQ MM0, MM0 + PUnpckLDQ MM1, MM1 + PUnpckLDQ MM2, MM2 + PUnpckLDQ MM3, MM3 + + PSRADI MM0, 13 + PSRADI MM1, 13 + PSRADI MM2, 13 + PSRADI MM3, 13 + + PackSSDW MM0, MM1 + PackSSDW MM2, MM3 + + MovQM [DI], MM0 + MovQM [DI+8], MM2 + + Add SI, 20h + Add DI, 10h + + Loop VSoundHandlerMono1 + +VSoundHandlerSend: + Mov CX, BytesToMix + Mov DX, BasePort + ShL CX, 2 + Add DX, 2 + Mov SI, MixTransferOffset + Rep OutsB + + Jmp VSoundHandler3 + +EndP VSoundFillBuffer + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc VSoundHandler + + PushAD + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Add TimerAccumulator, TIMERCONST + JC VSoundHandler1 + + Mov AL, 20h + Out 20h, AL + Jmp VSoundHandler2 + +VSoundHandler1: + PushF + Call [OldTimerIRQHandler] + +VSoundHandler2: + Add InVSound, 1 + JNC VSoundExit + + FNSave [FPSave] + Call SaveEMSPageFrame + + Assume DS:Nothing + Call VSoundFillBuffer + + Call RestoreEMSPageFrame + FNRstor [FPSave] + +VSoundExit: + Pop ES + Pop DS + PopAD + + Sub CS:InVSound, 1 + IRet + +EndP VSoundHandler + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov AL, 34h ; Program IRQ 0. LSB&MSB, Rate gen + Out 43h, AL ; bump the interrupt to be called + ; 100 times a second. + Mov AX, TIMERCONST + Out 40h, AL + Mov AL, AH + Out 40h, AL + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset VSoundHandler + + ClI + + XChg [ES:20h], EAX ; Hook to timer interrupt + Mov CS:OldTimerIRQHandler, EAX + + StI + + Pop ES + PopAD + + Ret + +EndP SetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov AL, 34h ; Program IRQ 0. LSB&MSB, Rate gen + Out 43h, AL + + Xor AL, AL + Out 40h, AL ; Interrupt called at normal 18.2 times + Out 40h, AL + + Mov EAX, CS:OldTimerIRQHandler + Mov [ES:20h], EAX + + Pop ES + PopAD + + Ret + +EndP ResetIRQ + Assume DS:Nothing + + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + FNInit + FILd DWord Ptr [MixSpeed] + FMul FreqMultiplier + FStP FreqMultiplier + + Mov SI, Offset RelocationTable + +RelocationFix: + LodsW + Test AX, AX + JZ RelocationEnd + Mov BX, AX + Mov [BX], DS + Jmp RelocationFix + + +RelocationEnd: + Call GetEMSPageFrame + Mov EMSPageFrame, AX + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + ; Parags to allocate = (8/(.4*31*16))*MixSpeed + ; = .04032258*MixSpeed = (65536*.04032258*MixSpeed) / 65536 + + Mov AX, 2643 + Mul MixSpeed + Add AX, 0FFFFh + AdC DX, 5 + Mov BX, DX + Mov AH, 48h + Int 21h + + Mov SI, Offset VSoundNoMemoryMsg + JNC InitSound1 + + Pop ES + Ret + +InitSound1: + Mov MixSegment, AX + + Call SetIRQ + Call GetTempo + Call SetTempo + + Mov SI, Offset VSoundDriverMsg + Mov AX, BasePort + + ClC + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + Push CS + Pop DS + + Mov SI, Offset NoReinitMsg + Mov BX, 40 + Call SetInfoLine + + Ret + +EndP ReInitSound + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Call GotoHomeDirectory + + Mov DS, Word Ptr [CS:DriverName+2] + Mov DX, Word Ptr [CS:DriverName] + + Mov AX, 3D02h ; Read write access + Int 21h + + Push CS + Pop DS + Assume DS:Driver + + JC SaveConfig2 + + Mov BX, AX + + Mov AX, 4200h + Xor CX, CX + Mov DX, Offset CONFIGURATIONOFFSET + Int 21h + JC SaveConfig1 + + Mov AH, 40h + Mov CX, CONFIGSIZE + Mov DX, Offset MixMode + Int 21h + +SaveConfig1: + Mov AH, 3Eh + Int 21h + +SaveConfig2: + Mov AX, MixSegment + Test AX, AX + JZ UnInitSound1 + + Mov ES, AX + Mov AH, 49h ; Release MixSegment + Int 21h + + Call ResetIRQ + +UnInitSound1: + Mov DX, BasePort + Mov AL, 3 + Out DX, AL + + Ret + +EndP UnInitSound + Assume DS:Nothing + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + ClI + Add CS:InVSound, 1 + JNC Poll1 + + Call VSoundFillBuffer + +Poll1: + Sub CS:InVSound, 1 + StI + + Ret + +EndP Poll + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + Assume DS:Nothing + + Push AX + Push BX + Push DX + + Push BX + + Mov AX, MixSpeed + Mov BX, AX + Xor DX, DX + + ShL AX, 1 + RCL DX, 1 ; DX:AX = Mixspeed*2 + + ShR BX, 1 ; BX = Mixspeed/2 + + Add AX, BX + AdC DX, 0 ; DX:AX = Mixspeed*2.5 + + Pop BX ; BX = tempo + Div BX + + Mov BytesToMix, AX + + Pop DX + Pop BX + Pop AX + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + Mov CS:MixVolume, AX + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Jmp CS:RecalculateAllVolumes + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Mov CS:Stereo, AL + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +include loadsam.inc + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset VSoundScreenList + + ClC + + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far + + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far + + Ret + +EndP SetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +InterpretState DB 0 +InterpretType DB 0 + +Proc SendUARTOut Far ; Local interpreter activated with 0F0h 0F0h. + + Mov AH, CS:InterpretState + Cmp AH, 2 + JB SendUARTOut1 + +; In interpreter. + JE SendUARTOut3 + +; Have InterpretType, now get parameter, then return to normal. + + Cmp AL, 7Fh + JA SendUARTOut4 + + Push BX + + Mov BL, CS:InterpretType ; Want BX = InterpretType*64+Channel + ; + ShL BX, 6 + Add BL, [DI+20h] + And BX, 127 + Mov [CS:FilterParameters+BX], AL + + Pop BX + + Test SI, SI + JZ SendUARTOut4 + + Or Byte Ptr [SI], 64 + +SendUARTOut4: + Mov CS:InterpretState, 0 + Ret + +SendUARTOut3: + Cmp AL, 2 + JAE SendUARTOut4 + + Mov CS:InterpretType, AL + Jmp SendUARTOutStateInc + +SendUARTOut1: + Cmp AL, 0F0h + JNE SendUARTOut2 + +SendUARTOutStateInc: + Inc CS:InterpretState + Ret + +SendUARTOut2: + Test AH, AH + JZ SendUARTOutEnd + + Push AX + Mov AL, 0F0h +; Call UARTOut + Pop AX + Mov CS:InterpretState, 0 + +SendUARTOutEnd: + Cmp AL, 0FCh + JE ResetFilters + Cmp AL, 0FAh + JE ResetFilters + + Cmp AL, 0FFh + JNE SendUARTOutNoClear + +ResetFilters: + PushA + Push ES + + Push CS + Pop ES + + Mov DI, Offset FilterParameters + Mov CX, 64 + Mov AL, 7Fh + Rep StosB + Mov CX, 64 + Xor AX, AX + Rep StosB + + Pop ES + PopA + +SendUARTOutNoClear: +; Call UARTOut + Ret + +EndP SendUARTOut + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. + DW 0 +DefaultChannels DW 128 + DW 3 + DW 4 Dup (0) + + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + DW Offset SendUARTOut + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/VTABLE.INC b/SoundDrivers/VTABLE.INC new file mode 100755 index 0000000..18d8fc6 --- /dev/null +++ b/SoundDrivers/VTABLE.INC @@ -0,0 +1,11 @@ + +VariableTableStart Label + +BasePort DW 0FFFFh +IRQ DW 0FFFFh +DMA DW 0FFFFh +CmdLineMixSpeed DW 0 +SongDataArea DW 0 + DB 16-($-VariableTableStart) Dup (0) + + diff --git a/SoundDrivers/WAV.MIX b/SoundDrivers/WAV.MIX new file mode 100755 index 0000000..1599879 --- /dev/null +++ b/SoundDrivers/WAV.MIX @@ -0,0 +1,1608 @@ +; +; WAV output mix functions.... +; Uses Cubic Spline Interpolation +; + +ALIGN 4 + +WAVMixingTable Label + ; 8 bit, 16 bit + ; No sound, stereo, surround + ; No loop, forwards loop, ping pong loop + + DW Offset UpdateNoLoop, 0, 0, 0, 0 + DW Offset UpdateForwardsLoop, 0, 0, 0, 0 + DW Offset UpdatePingPongLoop, 0, 0, 0, 0 + + DW Offset MixNoLoop, PreM32SMix8Bit, MFS8Bit, MBS8Bit, Mix32Stereo8Bit + DW Offset MixForwardsLoop, PreM32SMix8Bit, MFS8Bit, MBS8Bit, Mix32Stereo8Bit + DW Offset MixPingPongLoop, PreM32SMix8Bit, MFS8Bit, MBS8Bit, Mix32Stereo8Bit + + DW Offset MixNoLoop, PreM32UMix8Bit, MFS8Bit, MBS8Bit, Mix32Surround8Bit + DW Offset MixForwardsLoop, PreM32UMix8Bit, MFS8Bit, MBS8Bit, Mix32Surround8Bit + DW Offset MixPingPongLoop, PreM32UMix8Bit, MFS8Bit, MBS8Bit, Mix32Surround8Bit + + DW Offset UpdateNoLoop, 0, 0, 0, 0 + DW Offset UpdateForwardsLoop, 0, 0, 0, 0 + DW Offset UpdatePingPongLoop, 0, 0, 0, 0 + + DW Offset MixNoLoop, PreM32SMix16Bit, MFS16Bit, MBS16Bit, Mix32Stereo16Bit + DW Offset MixForwardsLoop, PreM32SMix16Bit, MFS16Bit, MBS16Bit, Mix32Stereo16Bit + DW Offset MixPingPongLoop, PreM32SMix16Bit, MFS16Bit, MBS16Bit, Mix32Stereo16Bit + + DW Offset MixNoLoop, PreM32UMix16Bit, MFS16Bit, MBS16Bit, Mix32Surround16Bit + DW Offset MixForwardsLoop, PreM32UMix16Bit, MFS16Bit, MBS16Bit, Mix32Surround16Bit + DW Offset MixPingPongLoop, PreM32UMix16Bit, MFS16Bit, MBS16Bit, Mix32Surround16Bit + +LastLeftValue DD 0 +LastRightValue DD 0 + +Sample1 DD 0 +Sample2 DD 0 +Sample3 DD 0 +Sample4 DD 0 +SampleValue DD 0 +InterpolationOffset DD 0 +Const3 DD 3.0 +Const1On65536 DD 37800000h +Const256On6 DD 422AAAAAh +Const1On6 DD 3E2AAAAAh +;Const65536 DD 65536.0 +Const32768 DD 32768.0 +Const1On32768 DD 38000000h +;ConstLimiter DD 3F000000h +Const22713_0 DD 22713.0 + +MAXFILTERVALUE EQU 47000000h + +FILTERCLIPPINGTYPENONE EQU 0 +FILTERCLIPPINGTYPECOMPRESSOR EQU 1 +FILTERCLIPPINGTYPELIMIT EQU 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Get8BitWaveform Macro ; Puts waveform value in EBX, range -32k->+32k + Local X + + +IF CUBICINTERPOLATION + + Mov BX, DI + + Push EDX + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Sub BX, 1 + Mov InterpolationOffset, ECX + AdC BX, 0 + + FILD InterpolationOffset + FMul Const1On65536 + + MovSX EAX, Byte Ptr [ES:BX] + MovSX EBX, Byte Ptr [ES:DI] + Mov Sample1, EAX + Mov Sample2, EBX + FILD Sample1 + FILD Sample2 + FMul Const3 + + MovSX EAX, Byte Ptr [ES:DI+1] + MovSX EBX, Byte Ptr [ES:DI+2] + Mov Sample3, EAX + Mov Sample4, EBX + FILD Sample3 + FMul Const3 + FILD Sample4 ; x, 3w, 3v, u, Interp + +; a = x+3v-3w-u +; b = 3w+3u-6v +; c = 6w-2u-x-3v +; d = 6v + +; Assignments: +; F = x+3v +; -> a = F-3w-u +; -> b = 3w+3u-6v +; -> c = 6w-2u-F +; -> d = 6v + +IF INTELOPTIMISED + FAdd ST, ST(2) ; x+3v[3], 3w, 3v, u, Interp + FLd ST(1) ; 3w, x+3v[3], 3w, 3v, u, Interp + FAdd ST, ST(4) ; 3w+u[3], x+3v[2], 3w, 3v, u, Interp + FXCh ST(4) ; u, x+3v[2], 3w, 3v, 3w+u[3], Interp + FAdd ST, ST ; 2u[3], x+3v[1], 3w, 3v, 3w+u[2], Interp + FXCh ST(3) ; 3v, x+3v[1], 3w, 2u[3], 3w+u[2], Interp + FLd ST(1) ; x+3v, 3v, x+3v, 3w, 2u[3], 3w+u[1], Interp + FSub ST, ST(5) ; a[3], 3v, x+3v, 3w, 2u[2], 3w+u, Interp + FXCh ; 3v, a[3], x+3v, 3w, 2u[2], 3w+u, Interp + FAdd ST, ST ; 6v[3], a[2], x+3v, 3w, 2u[1], 3w+u, Interp + FXCh ST(5) ; 3w+u, a[2], x+3v, 3w, 2u[1], 6v[3], Interp + FAdd ST, ST(4) ; 3w+3u[3], a[1], x+3v, 3w, 2u, 6v[2], Interp + FXCh ; a[1], 3w+3u[3], x+3v, 3w, 2u, 6v[2], Interp + FMul ST, ST(6) ; ax[3], 3w+3u[2], x+3v, 3w, 2u, 6v[1], Interp + FXCh ST(2) ; x+3v, 3w+3u[2], ax[3], 3w, 2u, 6v[1], Interp + FAddP ST(4), ST ; 3w+3u[1], ax[2], 3w, 2u+F[3], 6v, Interp + FSub ST, ST(4) ; 3w+3u-6v[3], ax[1], 3w, 2u+F[2], 6v, Interp + FXCh ST(2) ; 3w, ax[1], b[3], 2u+F[1], 6v, Interp + FAdd ST, ST ; 6w[3], ax, b[2], 2u+F, 6v, Interp + FXCh ; ax, 6w[3], b[2], 2u+F, 6v, Interp + FAddP ST(2), ST ; 6w[1], ax+b[3], 2u+f, d, Interp + FSubRP ST(2), ST ; ax+b, c[3], d, Interp + FMul ST, ST(3) ; ax^2+bx[3], c[2], d, Interp + FXCh ST(3) ; Interp, c[2], d, ax^2+bx[3] + FMul Const256On6 ; sInterp[3], c, d, ax^2+bx[1] + FXCh ; c, sInterp[3], d, ax^2+bx[1] + FAddP ST(3), ST ; sInterp[2], d, ax^2+bx+c[3] + FXCh ; d, sInterp[2], ax^2+bx+c[3] + FMul Const256On6 ; sd[3], sInterp[1], ax^2+bx+c[2] + FXCh ; sInterp[1], sd[3], ax^2+bx+c[2] + FMulP ST(2), ST + + Pop DS + Assume DS:Nothing + Mov EDX, [DS:0] + + FAdd ; SampleValue (16 bit value) + + FLd DWord Ptr [DS:0] ; x(k-1), x(k) + FMul DWord Ptr [DS:14h] ; b.x(k-1), x(k) + FLd DWord Ptr [DS:4] ; x(k-2), b.x(k-1), x(k) + FMul DWord Ptr [DS:18h] ; c.x(k-2), b.x(k-1), x(k) + FXCh ST(2) ; x(k), b.x(k-1), c.x(k-2) + FMul DWord Ptr [DS:10h] ; a.x(k), b.x(k-1), c.x(k-2) + FXCh ST(2) ; c.x(k-2), b.x(k-1), a.x(k) + FAdd + Mov EDX, [DS:0] + FAdd + + Mov [DS:4], EDX + + FSt DWord Ptr [DS:0] + FIStP CS:SampleValue + +ELSE + FAdd ST, ST(2) ; x+3v, 3w, 3v, u, Interp + FLd ST(1) ; 3w, x+3v, 3w, 3v, u, Interp + FSub ST, ST(4) ; 3w-u, x+3v, 3w, 3v, u, Interp + FAdd ST, ST ; 6w-2u, x+3v, 3w, 3v, u, Interp + FSub ST, ST(1) ; "c", x+3v, 3w, 3v, u, Interp + FXCh ; x+3v, "c", 3w, 3v, u, Interp + FSub ST, ST(2) ; x+3v-3w, "c", 3w, 3v, u, Interp + FSub ST, ST(4) ; "a", "c", 3w, 3v, u, Interp + FMul ST, ST(5) ; "ax", "c", 3w, 3v, u, Interp + FXCh ST(3) ; 3v, "c", 3w, "ax", u, Interp + FAdd ST, ST ; 6v, "c", 3w, "ax", u, Interp + FXCh ST(4) ; u, "c", 3w, "ax", 6v, Interp + FMul Const3 ; 3u, "c", 3w, "ax", 6v, Interp + FSub ST, ST(4) ; 3u-6v, "c", 3w, "ax", 6v, Interp + FAdd ST, ST(2) ; "b", "c", 3w, "ax", 6v, Interp + FAdd ST, ST(3) ; "ax+b", "c", 3w, "ax", 6v, Interp + FMul ST, ST(5) ; "ax^2+bx", "c", 3w, "ax", 6v, Interp + FAdd ; ax^2+bx+c, 3w, "ax", 6v, Interp + FMulP ST(4), ST ; 3w, "ax", 6v, ax^3+bx^2+cx + FComPP ; 6v, ax^3+bx^2+cx + FAdd ; SampleValue + FMul Const256On6 ; x(k) + + Pop DS + Assume DS:Nothing + + FMul DWord Ptr [DS:10h] + + FLd DWord Ptr [DS:0] ; x(k-1), x(k) + FMul DWord Ptr [DS:14h] ; b.x(k-1), x(k) + FLd DWord Ptr [DS:4] ; x(k-2), b.x(k-1), x(k) + FMul DWord Ptr [DS:18h] ; c.x(k-2), b.x(k-1), x(k) + FAdd + Mov EDX, [DS:0] + FAdd + + Mov [DS:4], EDX + + FSt DWord Ptr [DS:0] + FIStP SampleValue + +ENDIF + Pop EDX + + IF FILTERCLIPPINGTYPENONE + ELSE + Mov EAX, [DS:0] + And EAX, 7FFFFFFFh + Cmp EAX, MAXFILTERVALUE + JBE X + + IF FILTERCLIPPINGTYPECOMPRESSOR + + Mov EBX, [DS:0] + FLd CS:Const22713_0 + FLd DWord Ptr [DS:0] + FAbs + FMul CS:Const1On32768 + FYL2X ; ST = ln(x/65536) / ln(2) * 65536 * ln(2) + FAdd CS:Const32768 + SAR EBX, 31 + FIStP SampleValue + Xor SampleValue, EBX + Sub SampleValue, EBX + +Comment ~ + Mov EBX, [DS:0] + FLd DWord Ptr [DS:0] + FAbs + FSub [CS:Const65536] + FMul [CS:ConstLimiter] + FAdd [CS:Const65536] + SAR EBX, 31 + FIStP SampleValue + Xor SampleValue, EBX + Sub SampleValue, EBX +; FILD SampleValue +; FStP DWord Ptr [DS:0] +~ + ENDIF + IF FILTERCLIPPINGTYPELIMIT + + Mov EBX, [DS:0] + Mov EAX, MAXFILTERVALUE + And EBX, 80000000h + Or EAX, EBX + Mov [DS:0], EAX + ENDIF +X: + ENDIF + Mov EBX, SampleValue + +ENDIF + +IF QUADRATICINTERPOLATION + + Push EDX + Push EBP + + MovSX EDX, Byte Ptr [ES:DI+2] ; v + MovSX EBX, Byte Ptr [ES:DI] ; t + MovSX EAX, Byte Ptr [ES:DI+1] ; u + + LEA EBP, [EBX+EDX] ; v+t + SAR EBP, 1 + Sub EBP, EAX ; (v+t)/2 - u + IMul EBP, ECX ; ax in 8.16 format + SAR EBP, 10 ; ax in 8.6 format + + ShL EAX, 7 ; EBX = 2u<<6 + Add EDX, EBX ; EDX = v+t + Add EBX, EBX ; EAX = 2t + Add EBP, EAX ; EBP = ax+2u + Add EDX, EBX ; 3t+v + ShL EDX, 5 ; (3t+v)/2 << 6 + Sub EBP, EDX ; ax+b + + ShL EBX, 7 + + IMul EBP, ECX ; ax^2+bx in 8.22 form + SAR EBP, 14 ; ax^2+bx in 8.8 form + + Add EBX, EBP ; ax^2+bx+c + + Pop EBP + Pop EDX +ENDIF + + +IF LINEARINTERPOLATION + MovSX EBX, Byte Ptr [ES:DI+1] + MovSX EAX, Byte Ptr [ES:DI] + Sub EBX, EAX + IMul EBX, ECX + SAR EBX, 8 + ShL EAX, 8 + Add EBX, EAX +ENDIF + +IF POINTSAMPLED + MovSX EBX, Byte Ptr [ES:DI] + ShL EBX, 8 +ENDIF + +EndM + +Get16BitWaveform Macro ; Puts waveform value in EBX, range -32k->+32k + Local X + +IF CUBICINTERPOLATION + Mov EBX, EDI + + Push EDX + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Sub BX, 1 + Mov InterpolationOffset, ECX + AdC BX, 0 + + FILD InterpolationOffset + FMul Const1On65536 + + MovSX EAX, Word Ptr [ES:EBX+EBX] + MovSX EBX, Word Ptr [ES:EDI+EDI] + Mov Sample1, EAX + Mov Sample2, EBX + FILD Sample1 + FILD Sample2 + FMul Const3 + + MovSX EAX, Word Ptr [ES:EDI+EDI+2] + MovSX EBX, Word Ptr [ES:EDI+EDI+4] + Mov Sample3, EAX + Mov Sample4, EBX + FILD Sample3 + FMul Const3 + FILD Sample4 ; x, 3w, 3v, u, Interp + + +; a = x+3v-3w-u +; b = 3w+3u-6v +; c = 6w-2u-x-3v +; d = 6v + +; Assignments: +; F = x+3v +; -> a = F-3w-u +; -> b = 3w+3u-6v +; -> c = 6w-2u-F +; -> d = 6v + +IF INTELOPTIMISED + FAdd ST, ST(2) ; x+3v[3], 3w, 3v, u, Interp + FLd ST(1) ; 3w, x+3v[3], 3w, 3v, u, Interp + FAdd ST, ST(4) ; 3w+u[3], x+3v[2], 3w, 3v, u, Interp + FXCh ST(4) ; u, x+3v[2], 3w, 3v, 3w+u[3], Interp + FAdd ST, ST ; 2u[3], x+3v[1], 3w, 3v, 3w+u[2], Interp + FXCh ST(3) ; 3v, x+3v[1], 3w, 2u[3], 3w+u[2], Interp + FLd ST(1) ; x+3v, 3v, x+3v, 3w, 2u[3], 3w+u[1], Interp + FSub ST, ST(5) ; a[3], 3v, x+3v, 3w, 2u[2], 3w+u, Interp + FXCh ; 3v, a[3], x+3v, 3w, 2u[2], 3w+u, Interp + FAdd ST, ST ; 6v[3], a[2], x+3v, 3w, 2u[1], 3w+u, Interp + FXCh ST(5) ; 3w+u, a[2], x+3v, 3w, 2u[1], 6v[3], Interp + FAdd ST, ST(4) ; 3w+3u[3], a[1], x+3v, 3w, 2u, 6v[2], Interp + FXCh ; a[1], 3w+3u[3], x+3v, 3w, 2u, 6v[2], Interp + FMul ST, ST(6) ; ax[3], 3w+3u[2], x+3v, 3w, 2u, 6v[1], Interp + FXCh ST(2) ; x+3v, 3w+3u[2], ax[3], 3w, 2u, 6v[1], Interp + FAddP ST(4), ST ; 3w+3u[1], ax[2], 3w, 2u+F[3], 6v, Interp + FSub ST, ST(4) ; 3w+3u-6v[3], ax[1], 3w, 2u+F[2], 6v, Interp + FXCh ST(2) ; 3w, ax[1], b[3], 2u+F[1], 6v, Interp + FAdd ST, ST ; 6w[3], ax, b[2], 2u+F, 6v, Interp + FXCh ; ax, 6w[3], b[2], 2u+F, 6v, Interp + FAddP ST(2), ST ; 6w[1], ax+b[3], 2u+f, d, Interp + FSubRP ST(2), ST ; ax+b, c[3], d, Interp + FMul ST, ST(3) + FXCh ST(3) ; Interp, c[2], d, ax^2+bx[3] + FMul Const1On6 ; sInterp[3], c, d, ax^2+bx[1] + FXCh ; c, sInterp[3], d, ax^2+bx[1] + FAddP ST(3), ST ; sInterp[2], d, ax^2+bx+c[3] + FXCh ; d, sInterp[2], ax^2+bx+c[3] + FMul Const1On6 ; sd[3], sInterp[1], ax^2+bx+c[2] + FXCh ; sInterp[1], sd[3], ax^2+bx+c[2] + FMulP ST(2), ST + + Pop DS + Assume DS:Nothing + Mov EDX, [DS:0] + + FAdd ; SampleValue (16 bit value) + + FLd DWord Ptr [DS:0] ; x(k-1), x(k) + FMul DWord Ptr [DS:14h] ; b.x(k-1), x(k) + FLd DWord Ptr [DS:4] ; x(k-2), b.x(k-1), x(k) + FMul DWord Ptr [DS:18h] ; c.x(k-2), b.x(k-1), x(k) + FXCh ST(2) ; x(k), b.x(k-1), c.x(k-2) + FMul DWord Ptr [DS:10h] ; a.x(k), b.x(k-1), c.x(k-2) + FXCh ST(2) ; c.x(k-2), b.x(k-1), a.x(k) + FAdd + Mov EDX, [DS:0] + FAdd + + Mov [DS:4], EDX + + FSt DWord Ptr [DS:0] + FIStP CS:SampleValue + +ELSE + FAdd ST, ST(2) ; x+3v, 3w, 3v, u, Interp + FLd ST(1) ; 3w, x+3v, 3w, 3v, u, Interp + FSub ST, ST(4) ; 3w-u, x+3v, 3w, 3v, u, Interp + FAdd ST, ST ; 6w-2u, x+3v, 3w, 3v, u, Interp + FSub ST, ST(1) ; "c", x+3v, 3w, 3v, u, Interp + FXCh ; x+3v, "c", 3w, 3v, u, Interp + FSub ST, ST(2) ; x+3v-3w, "c", 3w, 3v, u, Interp + FSub ST, ST(4) ; "a", "c", 3w, 3v, u, Interp + FMul ST, ST(5) ; "ax", "c", 3w, 3v, u, Interp + FXCh ST(3) ; 3v, "c", 3w, "ax", u, Interp + FAdd ST, ST ; 6v, "c", 3w, "ax", u, Interp + FXCh ST(4) ; u, "c", 3w, "ax", 6v, Interp + FMul Const3 ; 3u, "c", 3w, "ax", 6v, Interp + FSub ST, ST(4) ; 3u-6v, "c", 3w, "ax", 6v, Interp + FAdd ST, ST(2) ; "b", "c", 3w, "ax", 6v, Interp + FAdd ST, ST(3) ; "ax+b", "c", 3w, "ax", 6v, Interp + FMul ST, ST(5) ; "ax^2+bx", "c", 3w, "ax", 6v, Interp + FAdd ; ax^2+bx+c, 3w, "ax", 6v, Interp + FMulP ST(4), ST ; 3w, "ax", 6v, ax^3+bx^2+cx + FComPP ; 6v, ax^3+bx^2+cx + FAdd ; SampleValue + FMul Const1On6 + + Pop DS + Assume DS:Nothing + + FMul DWord Ptr [DS:10h] + + FLd DWord Ptr [DS:0] ; x(k-1), x(k) + FMul DWord Ptr [DS:14h] ; b.x(k-1), x(k) + FLd DWord Ptr [DS:4] ; x(k-2), b.x(k-1), x(k) + FMul DWord Ptr [DS:18h] ; c.x(k-2), b.x(k-1), x(k) + FAdd + Mov EDX, [DS:0] + FAdd + + Mov [DS:4], EDX + + FSt DWord Ptr [DS:0] + FIStP SampleValue +ENDIF + Pop EDX + + IF FILTERCLIPPINGTYPENONE + ELSE + Mov EAX, [DS:0] + And EAX, 7FFFFFFFh + Cmp EAX, MAXFILTERVALUE + JBE X + + IF FILTERCLIPPINGTYPECOMPRESSOR + + Mov EBX, [DS:0] + FLd CS:Const22713_0 + FLd DWord Ptr [DS:0] + FAbs + FMul CS:Const1On32768 + FYL2X ; ST = ln(x/65536) / ln(2) * 65536 * ln(2) + FAdd CS:Const32768 + SAR EBX, 31 + FIStP SampleValue + Xor SampleValue, EBX + Sub SampleValue, EBX + +Comment ~ + Mov EBX, [DS:0] + FLd DWord Ptr [DS:0] + FAbs + FSub [CS:Const65536] + FMul [CS:ConstLimiter] + FAdd [CS:Const65536] + SAR EBX, 31 + FIStP SampleValue + XOr SampleValue, EBX + Sub SampleValue, EBX +; FILD SampleValue +; FStP DWord Ptr [DS:0] +~ + + ENDIF + IF FILTERCLIPPINGTYPELIMIT + + Mov EBX, [DS:0] + Mov EAX, MAXFILTERVALUE + And EBX, 80000000h + Or EAX, EBX + Mov [DS:0], EAX + ENDIF +X: + ENDIF + Mov EBX, SampleValue + +ENDIF + +IF QUADRATICINTERPOLATION + + Push ECX + Push EDX + Push EBP + + MovSX EDX, Word Ptr [ES:EDI+EDI+4] ; v + MovSX EBX, Word Ptr [ES:EDI+EDI] ; t + MovSX EAX, Word Ptr [ES:EDI+EDI+2] ; u + + ShR ECX, 3 ; 0.13 + LEA EBP, [EBX+EDX] + SAR EBP, 1 + Sub EBP, EAX ; (v+t)/2 - u + IMul EBP, ECX ; 16.13 + SAR EBP, 14 ; 15.0 + + Add EDX, EBX ; EDX = v+t + Add EBP, EAX ; EBP = ax+2u + LEA EDX, [EDX+EBX*2] + SAR EDX, 2 ; EDX = (3t+v)/2 + Sub EBP, EDX ; ax + b, 15 form + + IMul EBP, ECX ; ax^2+bx in 15.13 form + SAR EBP, 12 ; ax^2+bx in 16.0 form + + Add EBX, EBP + + Pop EBP + Pop EDX + Pop ECX + +ENDIF + +IF LINEARINTERPOLATION + MovSX EBX, Word Ptr [ES:EDI+EDI+2] + MovSX EAX, Word Ptr [ES:EDI+EDI] + Sub EBX, EAX + SAR EBX, 1 + IMul EBX, ECX + SAR EBX, 15 + Add EBX, EAX +ENDIF + +IF POINTSAMPLED + MovSX EBX, Word Ptr [ES:EDI+EDI] +ENDIF + +EndM + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Mix32Stereo8Bit ; Given DS:SI = buffer + ; Given ES:DI = sample + ; AX = bytes to mix + ; CX = error + ; DX = delta offset + ; BP = delta error + + ShL AX, 3 + Add AX, SI + Mov Word Ptr [CS:M32S8BEND], AX + +Mix32Stereo8Bit1: + Get8BitWaveForm + +M32S8BLVC EQU $+3 + IMul EAX, EBX, 12345678h + Sub [SI], EAX + + Mov CS:LastLeftValue, EAX + +M32S8BRVC EQU $+3 + IMul EAX, EBX, 12345678h + Sub [SI+4], EAX + + Mov CS:LastRightValue, EAX + + Add CX, BP + AdC DI, DX + Add SI, 8 + +M32S8BLVSet EQU $+2 + Mov EAX, 12345678h ; Destination volume left +M32S8BRVSet EQU $+2 + Mov EBX, 12345678h ; Destination volume right + + Sub EAX, DWord Ptr [CS:M32S8BLVC] ; Delta + Sub EBX, DWord Ptr [CS:M32S8BRVC] + + SAR EAX, RAMPSPEED + SAR EBX, RAMPSPEED + + Add DWord Ptr [CS:M32S8BLVC], EAX + Add DWord Ptr [CS:M32S8BRVC], EBX + +M32S8BNoRightRamp: + +M32S8BEND EQU $+2 + Cmp SI, 1234h + JNE Mix32Stereo8Bit1 + + Ret + +EndP Mix32Stereo8Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreM32SMix8Bit + +IF VOLUMERAMP + PushAD + + Xor EAX, EAX + Xor EBX, EBX + Xor EDX, EDX + Xor EBP, EBP + Xor EDI, EDI + + Mov AX, Word Ptr [SI+0Ch] ; New right volume + Mov BX, Word Ptr [SI+0Eh] ; New left volume + + Mov DX, Word Ptr [SI+1Ch] ; Old right volume + Mov BP, Word Ptr [SI+1Eh] ; Old left volume + + Mov DWord Ptr [CS:M32S8BRVC], EDX + Mov DWord Ptr [CS:M32S8BLVC], EBP + +; Compensate for upwards ramp. + + Cmp AX, DX + JB PreM32Mix8BitNoRightCompensate + + Add AX, RAMPCOMPENSATE + +PreM32Mix8BitNoRightCompensate: + + Cmp BX, BP + JB PreM32Mix8BitNoLeftCompensate + + Add BX, RAMPCOMPENSATE + +PreM32Mix8BitNoLeftCompensate: + Mov DWord Ptr [CS:M32S8BRVSet], EAX + Mov DWord Ptr [CS:M32S8BLVSet], EBX + +; Now to figure out exact final volumes + + Push SI + Mov CX, CS:RealBytesToMix + +PreM32Mix8Bit1: + Mov ESI, EAX ; Set values + Mov EDI, EBX + Sub ESI, EDX ; Current values + Sub EDI, EBP + SAR ESI, RAMPSPEED + SAR EDI, RAMPSPEED + Add EDX, ESI + Add EBP, EDI + + Loop PreM32Mix8Bit1 + + Pop SI + + Mov Word Ptr [SI+1Ch], DX + Mov Word Ptr [SI+1Eh], BP + + PopAD + Ret +ELSE + + Xor EAX, EAX + Xor EBX, EBX + + Mov AX, Word Ptr [SI+0Ch] + Mov BX, Word Ptr [SI+0Eh] + + Mov DWord Ptr [CS:M32S8BRVC], EAX + Mov DWord Ptr [CS:M32S8BLVC], EBX + + Mov DWord Ptr [CS:M32S8BRVSet], EAX + Mov DWord Ptr [CS:M32S8BLVSet], EBX + + Mov [SI+1Ch], AX + Mov [SI+1Eh], BX + + Ret +ENDIF + +EndP PreM32SMix8Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Mix32Surround8Bit ; Given DS:SI = buffer + ; Given ES:DI = sample + ; AX = bytes to mix + ; CX = error + ; DX = delta offset + ; BP = delta error + + ShL AX, 3 + Add AX, SI + Mov Word Ptr [CS:M32U8BEND], AX + +Mix32Surround8Bit1: + Get8BitWaveForm + +M32U8BLVC EQU $+3 + IMul EAX, EBX, 12345678h + Sub [SI], EAX + Mov CS:LastLeftValue, EAX + + Neg EAX +M32U8BLVSet EQU $+2 + Mov EBX, 12345678h + + Sub [SI+4], EAX + Sub EBX, DWord Ptr [CS:M32U8BLVC] + + + SAR EBX, RAMPSPEED + Add SI, 8 + + Add CX, BP + AdC DI, DX + + Add DWord Ptr [CS:M32U8BLVC], EBX + +M32U8BEND EQU $+2 + Cmp SI, 1234h + JNE Mix32Surround8Bit1 + + Mov EAX, CS:LastLeftValue + Neg EAX + Mov CS:LastRightValue, EAX + Ret + +EndP Mix32Surround8Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreM32UMix8Bit + +IF VOLUMERAMP + Xor EAX, EAX + Xor EBX, EBX + Mov AX, Word Ptr [SI+1Eh] ; Old + Mov BX, Word Ptr [SI+0Eh] ; New + Mov DWord Ptr [CS:M32U8BLVC], EAX + +; Compensate for upwards ramp. + + Cmp BX, AX + JB PreM32MixU8Bit2 + + Add BX, RAMPCOMPENSATE + +PreM32MixU8Bit2: + Mov DWord Ptr [CS:M32U8BLVSet], EBX + + Mov CX, CS:RealBytesToMix + +PreM32UMix8Bit1: + Mov EDX, EBX + Sub EDX, EAX + SAR EDX, RAMPSPEED + Add EAX, EDX + + Loop PreM32UMix8Bit1 + + Mov [SI+1Eh], AX + Ret + +ELSE + Xor EAX, EAX + Mov AX, Word Ptr [SI+0Eh] + Mov DWord Ptr [CS:M32U8BLVC], EAX + Mov DWord Ptr [CS:M32U8BLVSet], EAX + Mov [SI+1Eh], AX + + Ret +ENDIF + +EndP PreM32UMix8Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Mix32Stereo16Bit + + ShL AX, 3 + Add AX, SI + Mov Word Ptr [CS:M32S16BEND], AX + +Mix32Stereo16Bit1: + Get16BitWaveform + +M32S16BLVC EQU $+3 + IMul EAX, EBX, 12345678h + Sub [SI], EAX + + Mov CS:LastLeftValue, EAX + +M32S16BRVC EQU $+3 + IMul EAX, EBX, 12345678h + Sub [SI+4], EAX + + Mov CS:LastRightValue, EAX + + Add CX, BP + AdC DI, DX + +M32S16BLVSet EQU $+2 + Mov EAX, 12345678h ; Destination volume left +M32S16BRVSet EQU $+2 + Mov EBX, 12345678h ; Destination volume right + + Sub EAX, DWord Ptr [CS:M32S16BLVC] ; Delta + Sub EBX, DWord Ptr [CS:M32S16BRVC] + + SAR EAX, RAMPSPEED + SAR EBX, RAMPSPEED + + Add DWord Ptr [CS:M32S16BLVC], EAX + Add DWord Ptr [CS:M32S16BRVC], EBX + + Add SI, 8 + +M32S16BEND EQU $+2 + Cmp SI, 1234h + JNE Mix32Stereo16Bit1 + + Ret + +EndP Mix32Stereo16Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreM32SMix16Bit + +IF VOLUMERAMP + PushAD + + Xor EAX, EAX + Xor EBX, EBX + Xor EDX, EDX + Xor EBP, EBP + Xor EDI, EDI + + Mov AX, Word Ptr [SI+0Ch] ; New right volume + Mov BX, Word Ptr [SI+0Eh] ; New left volume + + Mov DX, Word Ptr [SI+1Ch] ; Old right volume + Mov BP, Word Ptr [SI+1Eh] ; Old left volume + + Mov DWord Ptr [CS:M32S16BRVC], EDX + Mov DWord Ptr [CS:M32S16BLVC], EBP + +; Compensate for upwards ramp. + + Cmp AX, DX + JB PreM32Mix16BitNoRightCompensate + + Add AX, RAMPCOMPENSATE + +PreM32Mix16BitNoRightCompensate: + + Cmp BX, BP + JB PreM32Mix16BitNoLeftCompensate + + Add BX, RAMPCOMPENSATE + +PreM32Mix16BitNoLeftCompensate: + Mov DWord Ptr [CS:M32S16BRVSet], EAX + Mov DWord Ptr [CS:M32S16BLVSet], EBX + +; Now to figure out exact final volumes + + Push SI + Mov CX, CS:RealBytesToMix + +PreM32Mix16Bit1: + Mov ESI, EAX ; Set values + Mov EDI, EBX + + Sub ESI, EDX ; Current values + Sub EDI, EBP + + SAR ESI, RAMPSPEED + SAR EDI, RAMPSPEED + + Add EDX, ESI + Add EBP, EDI + + Loop PreM32Mix16Bit1 + Pop SI + + Mov Word Ptr [SI+1Ch], DX + Mov Word Ptr [SI+1Eh], BP + + PopAD + Ret +ELSE + + Xor EAX, EAX + Xor EBX, EBX + + Mov AX, Word Ptr [SI+0Ch] + Mov BX, Word Ptr [SI+0Eh] + + Mov DWord Ptr [CS:M32S16BRVC], EAX + Mov DWord Ptr [CS:M32S16BLVC], EBX + + Mov DWord Ptr [CS:M32S16BRVSet], EAX + Mov DWord Ptr [CS:M32S16BLVSet], EBX + + Mov [SI+1Ch], AX + Mov [SI+1Eh], BX + + Ret +ENDIF + +EndP PreM32SMix16Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Mix32Surround16Bit ; Given DS:SI = buffer + ; Given ES:DI = sample + ; AX = bytes to mix + ; CX = error + ; DX = delta offset + ; BP = delta error + + ShL AX, 3 + Add AX, SI + Mov Word Ptr [CS:M32U16BEND], AX + +Mix32Surround16Bit1: + Get16BitWaveForm + +M32U16BLVC EQU $+3 + IMul EAX, EBX, 12345678h + Sub [SI], EAX + +M32U16BLVSet EQU $+2 + Mov EBX, 12345678h + + Neg EAX + Sub EBX, DWord Ptr [CS:M32U16BLVC] + + Sub [SI+4], EAX + + SAR EBX, RAMPSPEED + Add SI, 8 + + Add CX, BP + AdC DI, DX + + Add DWord Ptr [CS:M32U16BLVC], EBX + +M32U16BEND EQU $+2 + Cmp SI, 1234h + JNE Mix32Surround16Bit1 + + Mov CS:LastRightValue, EAX + Neg EAX + Mov CS:LastLeftValue, EAX + Ret + +EndP Mix32Surround16Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PreM32UMix16Bit + +IF VOLUMERAMP + Xor EAX, EAX + Xor EBX, EBX + Mov AX, Word Ptr [SI+1Eh] + Mov BX, Word Ptr [SI+0Eh] + Mov DWord Ptr [CS:M32U16BLVC], EAX + +; Compensate for upwards ramp. + + Cmp BX, AX + JB PreM32MixU16Bit2 + + Add BX, RAMPCOMPENSATE + +PreM32MixU16Bit2: + + Mov DWord Ptr [CS:M32U16BLVSet], EBX + + Mov CX, CS:RealBytesToMix + +PreM32UMix16Bit1: + Mov EDX, EBX + Sub EDX, EAX + SAR EDX, RAMPSPEED + Add EAX, EDX + + Loop PreM32UMix16Bit1 + + Mov [SI+1Eh], AX + Ret + +ELSE + Xor EAX, EAX + Mov AX, Word Ptr [SI+0Eh] + Mov DWord Ptr [CS:M32U16BLVC], EAX + Mov DWord Ptr [CS:M32U16BLVSet], EAX + Mov [SI+1Eh], AX + Ret +ENDIF + +EndP PreM32UMix16Bit + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +NUMBEROFFILTERBANDS EQU 4 + +ALIGN 4 +LastClickRemovalLeft DD 0 +LastClickRemovalRight DD 0 +StartingChannelOffset DW 0 +FilterParameters DB 64 Dup (7Fh), 64 Dup (0) +FilterValues DD 4*256 Dup (0) +SampleFilterCopyOffset DW 16*64 +FreqMultiplier DD 3A9F7867h ; = 1/(2*PI*110.0*2^0.25) +FreqParameterMultiplier DD 0B92AAAAAh ; = -1/(24*256) +FilterFreqValue DW 0 +NewControlWord DW 7Fh +include q.inc + +LastFilter DD NUMBEROFFILTERBANDS*2 Dup (0) ; 4 stereo values +FilterCoefficients DD NUMBEROFFILTERBANDS*2 Dup (0) +FilterVolumes DD NUMBEROFFILTERBANDS Dup (0) + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc IsSampleMode ; returns zero flag if sample mode. + + Push DS + + Mov DS, CS:SongDataArea + Test Byte Ptr [DS:2Ch], 4 + + Pop DS + Ret + +EndP IsSampleMode + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc M32MixHandler + ; Clear output buffer first... + + Mov CS:StartingChannelOffset, SI + + Push CX + + Mov ES, CS:MixSegment + Mov EAX, CS:BytesToMixFractional + Mov CX, CS:BytesToMix + Add CurrentFractional, EAX + AdC CX, 0 + Mov CS:RealBytestoMix, CX +; Add CX, CX ; Stereo = 2 * BytesToMix +; Mov DI, 32 +; Xor EAX, EAX +; Rep StosD + + Pop CX + + PushAD + + Mov EDX, CS:LastClickRemovalLeft + Mov EBP, CS:LastClickRemovalRight + +; Do left first. + Mov SI, 80 + Mov CX, CS:RealBytesToMix + +ClickRemoval3: + +Comment ~ + + Mov [ES:SI], EDX + Mov [ES:SI+4], EBP + + Inc EDX + JS ClickRemoval4 + + Sub EDX, 2 + JGE ClickRemoval4 + + Inc EDX + +ClickRemoval4: + Inc EBP + JS ClickRemoval5 + + Sub EBP, 2 + JGE ClickRemoval5 + + Inc EBP + +ClickRemoval5: +~ + + Mov EAX, EDX + Mov EBX, EBP + SAR EAX, 12 + SAR EBX, 12 + Mov [ES:SI], EDX + Mov [ES:SI+4], EBP + + Sub EAX, 1 + AdC EAX, 1 + Sub EBX, 1 + AdC EBX, 1 + + Sub EDX, EAX + Sub EBP, EBX + + Add SI, 8 + Loop ClickRemoval3 + + Mov CS:LastClickRemovalLeft, EDX + Mov CS:LastClickRemovalRight, EBP + + PopAD + + ; Check each channel... + ; Prepare mixing stuff + +; Work backwards + Mov AX, CX + Dec AX + ShL AX, 7 + Add SI, AX + +M32MixHandler1: + Test Byte Ptr [SI], 1 + JZ M32MixHandlerEnd2 + Cmp Byte Ptr [SI+36h], 100 + JE M32MixHandlerEnd2 + + Push CX + Mov BP, SI + Sub BP, [CS:StartingChannelOffset] ; BP = SlaveChannel*128 + SHR BP, 3 ; BP = SlaveChannel*16 + Mov DI, BP + Add BP, Offset FilterValues + + Mov CX, [SI] + Test CH, 2 + JZ M32MixHandler13 + + ; Note cut. + And Byte Ptr [SI], Not 1 ; Turn off channel + Mov Word Ptr [SI+4Ah], 0 + Or CL, 40h + +M32MixHandler13: + Test CL, 20h ; New freq? + JZ M32MixHandler3 + + Mov AX, [SI+10h] + Mov DX, [SI+12h] + Mov BX, MixSpeed + Cmp DX, BX + JAE M32MixHandlerError + + Div BX + ShL EAX, 16 + Xor AX, AX + Div BX + Mov STEPVALUE, EAX + +M32MixHandler3: + Test CH, 1 ; New note? + JZ M32MixHandler12 + + Xor EAX, EAX + Mov DWord Ptr [SI+1Ch], EAX + Mov DWord Ptr [CS:BP], EAX + Mov DWord Ptr [CS:BP+4], EAX + Mov DWord Ptr [CS:BP+8], 3F800000h + Mov DWord Ptr [CS:BP+0Ch], EAX + +M32MixHandler12: + Test CX, 8440h ; New volume, loop or pan? + JZ M32MixHandler4 + + Mov AL, [SI+3Ah] + Test AL, AL + JNS M32MixHandlerFilter1 + + Mov BL, [SI+3Fh] + Jmp M32MixHandlerFilter2 + +M32MixHandlerFilter1: + Mov DI, AX + And DI, 63 + Add DI, Offset FilterParameters + + Mov AL, [CS:DI] + Mov BL, [CS:DI+64] + Mov [SI+5Bh], AL + Mov [SI+3Fh], BL + +M32MixHandlerFilter2: + Mov AL, [SI+3Eh] + Mul Byte Ptr [SI+5Bh] + Mov CS:FilterFreqValue, AX + ShR AX, 8 + Mov AH, BL + AdC AX, 0 + + Cmp AX, 7Fh + JE M32MixHandlerNoFilter + + And BX, 0FFh + ShL BX, 2 + + FNInit + FLdCW [CS:NewControlWord] + + FILD [CS:FilterFreqValue] ; 0->127*256 + FMul [CS:FreqParameterMultiplier] ; -i/(24*256) + FLd ST + FRndInt + FSub ST(1), ST + FXCh + F2XM1 + FLd1 + FAdd + FScale ; = 2^(i/24*256) + FMul [CS:FreqMultiplier] ; = r + FLd ST ; r, r + FMul ST(1), ST ; r, r^2 + + FLd [CS:QualityFactorTable+BX] ; 2d, r, r^2 + FMul ST(1), ST ; 2d, 2dr, r^2 + FLd1 ; 1, 2d, 2dr, r^2 + FSubP ST(1), ST ; 2d-1, 2dr, r^2 + FAdd + + FLd1 ; 1, d, e + FAdd ST, ST(1) + FAdd ST, ST(2) ; 1+d+e, d, e + FLd1 ; 1, 1+d+e, d, e + FDivRP ST(1), ST ; 1/(1+d+e), d, e + FSt DWord Ptr [CS:BP+8] + FXCh ; d, 1/(1+d+e), e + FAdd ST, ST(2) + FAddP ST(2), ST ; 1/(1+d+e), d+2e + FMul + FStP DWord Ptr [CS:BP+0Ch] + FStP ST + +M32MixHandlerNoFilter: + +IF REGISTERED + Test CH, 8 + JNZ M32MixHandler7 + + Cmp CS:Stereo, 0 + JE M32MixHandler6 + + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE M32MixHandler6 + + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + SHRD AX, DX, 14 + + Mov [SI+0Ch], AX ; Store into right volume + + Mov AL, 64 ; Do left volume + Sub AL, [SI+37h] ; AL = 64-FinalPan + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] ; Final volume + SHRD AX, DX, 14 + Mov [SI+0Eh], AX + + ; Now to decide on mixing method + Cmp DWord Ptr [SI+0Ch], 0 + JNE M32MixHandler5 +ELSE + Test CH, 8 + JZ M32MixHandler6 + +ENDIF + +M32MixHandler7: + ; Zero volume + Xor EAX, EAX + Mov [SI+0Ch], EAX + Cmp [SI+1Ch], EAX ; Last volumes = 0? + JE M32MixHandler8 + +M32MixHandler5: ; Other.. (ie. panned) + Mov AX, 30 + Jmp M32MixHandler8 + +M32MixHandler6: ; Surround sound + Mov AX, [SI+4Ah] + Mul MixVolume + +IF REGISTERED + ShRD AX, DX, 8 + Cmp CS:Stereo, 0 + JE M32MixHandlerHalfStereoVolume + + ShR AX, 1 + +M32MixHandlerHalfStereoVolume: + +ELSE + + ShRD AX, DX, 9 +ENDIF + + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + + Test AX, AX + JNZ M32MixHandlerSurround1 + + Cmp DWord Ptr [SI+1Ch], 0 + JE M32MixHandler7 + +M32MixHandlerSurround1: + Mov AX, 60 + +M32MixHandler8: + Mov BL, [SI+0Ah] + Test Byte Ptr [SI+18h], 2 + JZ M32MixHandler9 + + Add AX, 90 + +M32MixHandler9: + Cmp BL, 8 + JB M32MixHandler11 ; No loop + JE M32MixHandler10 + + Add AX, 10 + +M32MixHandler10: + Add AX, 10 + +M32MixHandler11: + Add AX, Offset WAVMixingTable + Mov [SI+8], AX ; Offset... + +M32MixHandler4: + ; Mixing routine call... + Mov BX, [SI+8] ; BX = offset into + Mov EAX, [CS:BX+2] + Mov DWord Ptr PreMixFunction, EAX + Mov EAX, [CS:BX+6] + Mov DWord Ptr MixFunctionSeparateBackwards, EAX + + Mov AX, RealBytesToMix + Mov MixBlockSize, AX + Mov MixBufferOffset, 80 + + Mov EAX, CURRENTPOSITION + Mov OLDPOSITION, EAX + + Cmp CS:StartNoRamp, 0 + JE NoStartRamp + + Test CH, 1 + JZ NoStartRamp + Cmp DWord Ptr [SI+4Ch], 0 + JNE NoStartRamp + + Mov EAX, [SI+0Ch] + Mov [SI+1Ch], EAX + +NoStartRamp: + + Mov ES, CS:MixSegment ; Get filter data + Mov EAX, [CS:BP] ; Last sample 1 + Mov EDX, [CS:BP+4] ; Last sample 2 + Mov [ES:0], EAX + Mov [ES:4], EDX + Mov EAX, [CS:BP+8] ; Filtera + Mov EDX, [CS:BP+0Ch] ; Filterb + Mov [ES:10h], EAX + Mov [ES:14h], EDX + FLd1 + FSub DWord Ptr [ES:10h] + FSub DWord Ptr [ES:14h] + FStP DWord Ptr [ES:18h] ; Filterc + + Push BP + Call Word Ptr [CS:BX] + Pop BP + + Mov ES, CS:MixSegment ; Store filter data + Mov EAX, [ES:0] + Mov EDX, [ES:4] + Mov [CS:BP], EAX + Mov [CS:BP+4], EDX + + And Word Ptr [SI], 0111100010001101b + + Call IsSampleMode + JNE M32MixHandlerEnd + + Mov [CS:BP+16*64], EAX + Mov [CS:BP+16*64+4], EDX + Mov EAX, [CS:BP+8] + Mov EDX, [CS:BP+0Ch] + Mov [CS:BP+16*64+8], EAX + Mov [CS:BP+16*64+0Ch], EDX + + Jmp M32MixHandlerEnd + +M32MixHandlerError: + Mov Word Ptr [SI], 200h + + Test Byte Ptr [SI+3Ah], 80h + JNZ M32MixHandlerEnd + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Turn off channel + +M32MixHandlerEnd: + Pop CX + +M32MixHandlerEnd2: + Sub SI, 128 + Dec CX + JNZ M32MixHandler1 + + Push CS + Pop DS + Assume DS:Driver + + Xor DI, DI + Mov SI, Offset LastFilter + Mov CX, 80/4 + Mov ES, MixSegment + + Rep MovsD + +; Now do filtering. + FNInit + Mov CX, RealBytesToMix + + Push ES + Pop DS + Assume DS:Nothing + + Mov SI, 80 + +OutputFilter1: + FILD DWord Ptr [SI] ; Left sample + FILD DWord Ptr [SI+4] ; R, L + + FLd DWord Ptr [DS:20h] ; LB, R, L + FMul ST, ST(2) ; L.LB, R, L + FLd DWord Ptr [DS:20h] ; LB, L.LB, R, L + FMul ST, ST(2) ; R.LB, L.LB, R, L + FLd DWord Ptr [DS:0] ; OL, R.LB, L.LB, R, L + FMul DWord Ptr [DS:24h] ; OL.LB, R.LB, L.LB, R, L + FLd DWord Ptr [DS:4] ; OR, OL.LB, R.LB, L.LB, R, L + FMul DWord Ptr [DS:24h] ; OR.LB, OL.LB, R.LB, L.LB, R, L + + FXCh ; OL.LB, OR.LB, R.LB, L.LB, R, L + FAddP ST(3), ST + FAdd ; RLB, LLB, R, L + + FLd DWord Ptr [DS:28h] ; MB, RLB, LLB, R, L + FMul ST, ST(4) ; L.MB, RLB, LLB, R, L + FLd DWord Ptr [DS:28h] ; MB, L.MB, RLB, LLB, R, L + FMul ST, ST(4) ; R.MB, L.MB, RLB, LLB, R, L + FLd DWord Ptr [DS:8] ; OL, R.MB, L.MB, RLB, LLB, R, L + FMul DWord Ptr [DS:2Ch] ; OL.MB, R.MB, L.MB, RLB, LLB, R, L + FLd DWord Ptr [DS:0Ch] ; OR, OL.MB, R.MB, L.MB, RLB, LLB, R, L + FMul DWord Ptr [DS:2Ch] ; OR.MB, OL.MB, R.MB, L.MB, RLB, LLB, R, L + + FXCh ; OL.MB, OR.MB, R.MB, L.MB, RLB, LLB, R, L + FAddP ST(3), ST + FAdd ; RMB, LMB, RLB, LLB, R, L + FXCh ST(3) ; LLB, LMB, RLB, RMB, R, L + FStP DWord Ptr [DS:0] + FStP DWord Ptr [DS:8] + FStP DWord Ptr [DS:4] + FStP DWord Ptr [DS:0Ch] + + FLd DWord Ptr [DS:30h] + FMul ST, ST(2) + FLd DWord Ptr [DS:30h] + FMul ST, ST(2) + FLd DWord Ptr [DS:10h] + FMul DWord Ptr [DS:34h] + FLd DWord Ptr [DS:14h] + FMul DWord Ptr [DS:34h] + + FXCh + FAddP ST(3), ST + FAdd + + FLd DWord Ptr [DS:38h] + FMul ST, ST(4) + FLd DWord Ptr [DS:38h] + FMul ST, ST(4) + FLd DWord Ptr [DS:18h] + FMul DWord Ptr [DS:3Ch] + FLd DWord Ptr [DS:1Ch] + FMul DWord Ptr [DS:3Ch] + + FXCh + FAddP ST(3), ST + FAdd + FXCh ST(3) + FStP DWord Ptr [DS:10h] + FStP DWord Ptr [DS:18h] + FStP DWord Ptr [DS:14h] + FStP DWord Ptr [DS:1Ch] ; R, L + +; For each one, output value += ((band value) - (previous band value)) * Volume + + FLd DWord Ptr [DS:18h] + FSub DWord Ptr [DS:10h] ; L4, R, L + FLd DWord Ptr [DS:1Ch] + FSub DWord Ptr [DS:14h] ; R4, L4, R, L + FLd DWord Ptr [DS:10h] + FSub DWord Ptr [DS:8] + FLd DWord Ptr [DS:14h] + FSub DWord Ptr [DS:0Ch] ; R3, L3, R4, L4, R, L + FLd DWord Ptr [DS:8] + FSub DWord Ptr [DS:0] + FLd DWord Ptr [DS:0Ch] + FSub DWord Ptr [DS:4] ; R2, L2, R3, L3, R4, L4, R, L + FXCh ST(5) ; L4, L2, R3, L3, R4, R2, R, L + FMul DWord Ptr [DS:4Ch] ; L4V, L2, R3, L3, R4, R2, R, L + FXCh ST(4) ; R4, L2, R3, L3, L4V, R2, R, L + FMul DWord Ptr [DS:4Ch] ; R4V, L2, R3, L3, L4V, R2, R, L + FXCh ST(3) ; L3, L2, R3, R4V, L4V, R2, R, L + FMul DWord Ptr [DS:48h] ; L3V, L2, R3, R4V, L4V, R2, R, L + FXCh ST(2) ; R3, L2, L3V, R4V, L4V, R2, R, L + FMul DWord Ptr [DS:48h] ; R3V, L2, L3V, R4V, L4V, R2, R, L + FXCh ; L2, R3V, L3V, R4V, L4V, R2, R, L + FMul DWord Ptr [DS:44h] ; L2V, R3V, L3V, R4V, L4V, R2, R, L + FXCh ST(5) ; R2, R3V, L3V, R4V, L4V, L2V, R, L + FMul DWord Ptr [DS:44h] ; R2V, R3V, L3V, R4V, L4V, L2V, R, L + FXCh ST(4) ; L4V, R3V, L3V, R4V, R2V, L2V, R, L + FAddP ST(7), ST ; R3V, L3V, R4V, R2V, L2V, R, L + FAddP ST(5), ST ; L3V, R4V, R2V, L2V, R, L + FAddP ST(3), ST + FAdd + FLd DWord Ptr [DS:0] + FMul DWord Ptr [DS:40h] ; L1V, RV, LV, R, L + FLd DWord Ptr [DS:4] ; + FMul DWord Ptr [DS:40h] ; R1V, L1V, RV, LV, R, L + FXCh ST(2) ; RV, L1V, R1V, LV, R, L + FAddP ST(4), ST ; L1V, R1V, LV, R, L + FAddP ST(4), ST ; R1V, LV, R, L + FAddP ST(2), ST + FAddP ST(2), ST + + FIStP DWord Ptr [SI+4] + FIStP DWord Ptr [SI] + + Add SI, 8 + Dec CX + JNZ OutputFilter1 + +; Transfer contents out + Push CS + Pop ES + + Mov DI, Offset LastFilter + Xor SI, SI + Mov CX, 32/4 + + Rep MovsD +; Finished output filtering! + + Ret + +EndP M32MixHandler + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ diff --git a/SoundDrivers/WAVDRV.ASM b/SoundDrivers/WAVDRV.ASM new file mode 100755 index 0000000..e2c9441 --- /dev/null +++ b/SoundDrivers/WAVDRV.ASM @@ -0,0 +1,1601 @@ + + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +STEREOENABLED EQU 1 +MIXRESOLUTION EQU 32 + +include ..\wavswitc.inc + +FileHandle DW 0 +NumClipped DD 0 + +WAVOutputMsg DB "Writing to disk", 13 + DB "Output frequency ", 0FDh, "D", 0 +WAVFileErrorMsg DB "Unable to create output file! ", 0 +WAVMemErrorMsg DB "Unable to allocate memory!", 0 +NoReinitMsg DB "File output routines should NOT require reinitialisation ", 0 +WriteError DB "Error writing to output file. Output file closed ", 0 +DefaultDriverName DB "ITWAV.DRV", 0 +DriverName DD 0 +ClippedMsg DB "Clipped ", 0FDh, "L", 0 + +WAVEFileHeader DB "RIFF" +WAVEFileSize DD 0 +WAVEFileHeader2 DB "WAVEfmt " +WAVEFileHeaderLength DD 10h +WAVEFileID DW 1 +WAVEChannels DW 1 ; 1 = mono, 2 = stereo +MixSpeed DW 44100 ; Default to CD quality +WAVEMixSpeedFiller DW 0 +WAVEBytesPerSecond DD 0 +WAVEBytesPerSample DW 2 +WAVEBits DW 16 +WAVEHeader3 DB "data" +WAVEDataSize DD 0 + +IF REGISTERED + Stereo DB 0 + StereoSet DB 0 +ENDIF + +BytesToMix DW 0 +RealBytesToMix DW 0 +BytesToMixFractional DD 0 +CurrentFractional DD 0 + +MixVolume DW 0 +MixSegment DW 0 +MixHandler DW Offset M32MixHandler +CONFIGURATIONOFFSET EQU $+128 +CONFIGSIZE EQU 90 +WAVDirectory DB ".", 79 Dup (0) +VolumeTable DB 0, 16, 96, 127 + DB 0, 0, 0, 0 +StartNoRamp DW 0 +OldDirectory DB 80 Dup (0) + +CreatingMsg DB "Creating file " +OutputFileName DB " ", 0 + +ClosedFileMsg DB "Finished writing file ", 0 +OUTPUT DB "OUTPUT" + +LongMixSpeed DD 0 + +IF DITHEROUTPUT +MonoDitherValue DD 0 +LeftDitherValue DD 0 +RightDitherValue DD 0 +ENDIF + +WAVScreenList DW 6 + DW IdleFunctionList + DW GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr WAVHeader + + DW Near Ptr FilterBox1 + DW Near Ptr DirectoryInputBox + DW Near Ptr DirectoryInput ; 6 + + DW Near Ptr FilterBox2 + DW Near Ptr FilterFrequency1 ; 8 + DW Near Ptr FilterFrequency2 + DW Near Ptr FilterFrequency3 + DW Near Ptr FilterFrequency4 + DW Near Ptr FilterVolume1 + DW Near Ptr FilterVolume2 + DW Near Ptr FilterVolume3 + DW Near Ptr FilterVolume4 + + DW Near Ptr DirectoryInputText + DW Near Ptr FilterText + + DW Near Ptr StartRampText + DW Near Ptr StartRampEnabledButton ; 19 + DW Near Ptr StartRampDisabledButton + + DW 0 + +WAVHeader DW 10 + DB "WAV Driver", 0 + +StartRampText DW 1 + DB 2, 25 + DB 20h + DB "Ramp volume at start of sample", 0 + +StartRampEnabledButton DW 2 + DW 11, 0FFFFh, 20, 20 + DW 0, 0, 0 + DW 5 + DW Offset StartNoRampFunction +Seg1 DW 0 + DW 0 + DW 0, 0 + DB 33, 24, 47, 26 + DB 8, 0 + DB " Enabled", 0 + +StartRampDisabledButton DW 2 + DW 11, 0FFFFh, 19, 19 + DW 0, 0, 0 + DW 5 + DW Offset StartNoRampFunction +Seg2 DW 0 + DW 1 + DW 0, 0 + DB 48, 24, 62, 26 + DB 8, 0 + DB " Disabled", 0 + +IdleFunctionList DD 0 + DD 0 +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +DirectoryInputText DW 1 + DB 2, 14 + DB 20h + DB "Output Directory", 0 + +DirectoryInputBox DW 0 + DB 18, 13, 78, 15 + DB 25 + +DirectoryInput DW 16 + DB 19, 14 +Segment1 DW 0 + DW Offset WAVDirectory + DW 59 + DD 0 + DW 0FFFFh, 8, 0FFFFh, 0FFFFh + +FilterText DW 1 + DB 2, 17 + DB 20h + DB "Output Equalizer", 13 + DB 13 + DB " Low Frequency Band", 13 + DB " Med Low Frequency Band", 13 + DB "Med High Frequency Band", 13 + DB " High Frequency Band", 0 + +FilterBox1 DW 0 + DB 25, 18, 47, 23 + DB 25 + +FilterBox2 DW 0 + DB 52, 18, 74, 23 + DB 25 + +FilterFrequency1 DW 14 + DB 26, 19 + DW 0, 127 + DW 9, 0 + DW 6, 9, 12, 12 + DW 0FFFFh, 0FFFFh + DW 20 + +FilterFrequency2 DW 14 + DB 26, 20 + DW 0, 127 + DW 9, 1 + DW 8, 10, 13, 13 + DW 0FFFFh, 0FFFFh + DW 20 + +FilterFrequency3 DW 14 + DB 26, 21 + DW 0, 127 + DW 9, 2 + DW 9, 11, 14, 14 + DW 0FFFFh, 0FFFFh + DW 20 + +FilterFrequency4 DW 14 + DB 26, 22 + DW 0, 127 + DW 9, 3 + DW 10, 19, 15, 15 + DW 0FFFFh, 0FFFFh + DW 20 + +FilterVolume1 DW 14 + DB 53, 19 + DW 0, 255 + DW 9, 4 + DW 6, 13, 8, 8 + DW 0FFFFh, 0FFFFh + DW 20 + +FilterVolume2 DW 14 + DB 53, 20 + DW 0, 255 + DW 9, 5 + DW 12, 14, 9, 9 + DW 0FFFFh, 0FFFFh + DW 20 + +FilterVolume3 DW 14 + DB 53, 21 + DW 0, 255 + DW 9, 6 + DW 13, 15, 10, 10 + DW 0FFFFh, 0FFFFh + DW 20 + +FilterVolume4 DW 14 + DB 53, 22 + DW 0, 255 + DW 9, 7 + DW 14, 19, 11, 11 + DW 0FFFFh, 0FFFFh + DW 20 + +IF WAREZWAVE + Filename1 DB 01h, 0C8h, 0E6h, 01h, 0F5h, 0F7h, 0F7h, 03h, 0F4h, 0FEh, 0D4h, 01h, 0F5h, 0F7h, 0C2h ; COMMAND.COM + Filename2 DB 01h, 0C8h, 0E6h, 0FBh, 0F5h, 0D4h, 0F1h, 0EBh, 0F1h, 0C2h ; IO.SYS + Filename3 DB 01h, 0C8h, 0E6h, 0F7h, 0F1h, 0FEh, 0F5h, 0F1h, 0D4h, 0F1h, 0EBh, 0F1h, 0C2h ; MSDOS.SYS + LocalDirectory DB ".", 60 Dup(0) +ENDIF + +include mixwav.inc + +include wav.mix + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + + +Proc DetectCard Far + + Cmp BX, 217h + JAE DetectCardUseDriver + + Mov CX, DS + ShL ECX, 16 + Mov CX, Offset DefaultDriverName + +DetectCardUseDriver: + Mov [CS:DriverName], ECX + + Call GetEMSPageFrame + Mov EMSPageFrame, AX + + Mov Seg1, CS + MOv Seg2, CS + +IF WAREZWAVE + +; Decode things + Push CS + Push CS + Pop DS + Pop ES + Assume DS:Driver + + Mov CX, 3 + + Mov SI, Offset Filename1 + Mov DI, Offset Filename1 + +DetectCard1: + + LodsB + Sub AL, 24h + Xor AL, 9Eh + StosB + + JNZ DetectCard1 + Loop DetectCard1 + +ENDIF + + Mov EAX, 'Jeff' + ClC ; Always assume true + Ret + +EndP DetectCard + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +InterpretState DB 0 +InterpretType DB 0 + +Proc SendUARTOut Far ; Local interpreter activated with 0F0h 0F0h. + + Mov AH, CS:InterpretState + Cmp AH, 2 + JB SendUARTOut1 + +; In interpreter. + JE SendUARTOut3 + +; Have InterpretType, now get parameter, then return to normal. + + Cmp AL, 7Fh + JA SendUARTOut4 + + Push BX + + Mov BL, CS:InterpretType ; Want BX = InterpretType*64+Channel + ; + ShL BX, 6 + Add BL, [DI+20h] + And BX, 127 + Mov [CS:FilterParameters+BX], AL + + Pop BX + + Test SI, SI + JZ SendUARTOut4 + + Or Byte Ptr [SI], 64 + +SendUARTOut4: + Mov CS:InterpretState, 0 + Ret + +SendUARTOut3: + Cmp AL, 2 + JAE SendUARTOut4 + + Mov InterpretType, AL + Jmp SendUARTOutStateInc + +SendUARTOut1: + Cmp AL, 0F0h + JNE SendUARTOut2 + +SendUARTOutStateInc: + Inc CS:InterpretState + Ret + +SendUARTOut2: + Test AH, AH + JZ SendUARTOutEnd + + Mov CS:InterpretState, 0 + Ret + +SendUARTOutEnd: + Cmp AL, 0FCh + JE ResetFilters + Cmp AL, 0FAh + JE ResetFilters + + Cmp AL, 0FFh + JNE SendUARTOutNoClear + +ResetFilters: + PushA + Push ES + + Push CS + Pop ES + + Mov DI, Offset FilterParameters + Mov CX, 64 + Mov AL, 7Fh + Rep StosB + Mov CX, 64 + Xor AX, AX + Rep StosB + + Pop ES + PopA + +SendUARTOutNoClear: + Ret + +EndP SendUARTOut + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov Segment1, DS + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + Call GotoHomeDirectory + Mov SI, Offset WAVDirectory + Call SetDirectory + + Mov AH, 48h + Mov BX, 2648 ; (65536 / (.4*31)) * 4 * 2 + ; +80 (filtering area) + Int 21h + JNC InitSound1 + + Mov SI, Offset WAVMemErrorMsg + Ret + +InitSound1: + Mov MixSegment, AX + + Mov SI, Offset WAVOutputMsg + + Mov AX, CmdLineMixSpeed + And AX, AX + JZ InitSound3 + + Cmp AX, 8000 + JA InitSound4 + + Mov AX, 8000 + +InitSound4: + Cmp AX, 64000 + JB InitSound5 + + Mov AX, 64000 + +InitSound5: + Mov MixSpeed, AX + +InitSound3: + Mov AX, MixSpeed + Mov Word Ptr LongMixSpeed, AX + + FNInit + FILd DWord Ptr [MixSpeed] + FMul FreqMultiplier + FStP FreqMultiplier + + Call CalculateFilterCoefficients + + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + Push CS + Pop DS + + Mov SI, Offset NoReinitMsg + Mov BX, 40 + Call SetInfoLine + + Ret + +EndP ReInitSound + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Call GotoHomeDirectory + + Mov DS, Word Ptr [CS:DriverName+2] + Mov DX, Word Ptr [CS:DriverName] + + Mov AX, 3D02h ; Read write access + Int 21h + + Push CS + Pop DS + Assume DS:Driver + + JC SaveConfig2 + + Mov BX, AX + + Mov AX, 4200h + Xor CX, CX + Mov DX, Offset CONFIGURATIONOFFSET + Int 21h + JC SaveConfig1 + + Mov AH, 40h + Mov CX, CONFIGSIZE + Mov DX, Offset WAVDirectory + Int 21h + +SaveConfig1: + Mov AH, 3Eh + Int 21h + +SaveConfig2: + Mov AX, MixSegment + Test AX, AX + JZ UnInitsound1 + + Mov ES, AX + Mov AH, 49h + Int 21h + +UnInitSound1: + Mov BX, FileHandle + Test BX, BX + JZ UnInitSound2 + + Mov AX, 4200h ; Move to start of file + Xor CX, CX + Xor DX, DX + Int 21h ; Start of file + + Mov EAX, WAVEDataSize + Add EAX, 24h + Mov WAVEFileSize, EAX + + Mov AH, 40h + Mov DX, Offset WAVEFileHeader + Mov CX, 2Ch + Int 21h + + Mov AH, 3Eh + Int 21h + +UnInitSound2: + Ret + +EndP UnInitSound + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc CopyFileName ; Given DI + + Push DS + + Call GetFileName + Assume DS:Nothing ; Returns DS:SI + + Push CS + Pop ES + Mov CX, 11 + Mov AL, ' ' + Push DI + Rep StosB + Pop DI + + Mov CX, 8 + + Cmp Byte Ptr [SI], 0 + JE CopyFileName2 + Cmp Byte Ptr [SI], '.' + JE CopyFileName2 + +CopyFileName1: + LodsB + Cmp AL, '.' + JE CopyFileName3 + StosB + Loop CopyFileName1 + + Pop DS + Ret + +CopyFileName2: + Push CS + Pop DS + Mov SI, Offset OUTPUT + Mov CX, 6 + Rep MovsB + +CopyFileName3: + Pop DS + Ret + +EndP CopyFileName + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; BX = pattern +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +SlaveChannelLocation DW 0, 0, 0 + +Proc Poll Far + + Cmp MixSegment, 0 + JNE Poll2 + + Ret + +Poll2: + Push BX + Call Update ; Got DS:SI, CX + Pop BX + + Mov CS:[SlaveChannelLocation], SI + Mov CS:[SlaveChannelLocation+2], DS + Mov CS:[SlaveChannelLocation+4], CX + + Test AX, AX + JNZ Poll1 + + Cmp CS:FileHandle, 0 + JE Poll7 + + PushAD + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov SI, Offset ClosedFileMsg + Mov BX, 100 + Call SetInfoLine + +PollCloseFile: + Xor BX, BX + XChg BX, FileHandle + Mov AX, 4200h ; Move to start of file + Xor CX, CX + Xor DX, DX + Int 21h ; Start of file + + Mov EAX, WAVEDataSize + Add EAX, 24h + Mov WAVEFileSize, EAX + + Mov AH, 40h + Mov DX, Offset WAVEFileHeader + Mov CX, 2Ch + Int 21h + + Mov AH, 3Eh ; Close file + Int 21h + + Pop DS + PopAD + Assume DS:Nothing + Ret + +Poll7: +IF REGISTERED + Mov AL, CS:StereoSet + Mov CS:Stereo, AL +ENDIF + Ret + +Poll1: + PushAD + Push DS + Push ES + + Cmp CS:FileHandle, 0 + JNE Poll8 + ; Create file... BX = pattern + + Push AX + + Push CS + Push CS + Pop DS + Pop ES + Assume DS:Driver + + Xor EAX, EAX + Mov LastClickRemovalLeft, EAX + Mov LastClickRemovalRight, EAX + Mov NumClipped, EAX + Mov CurrentFractional, EAX +IF DITHEROUTPUT + Mov MonoDitherValue, EAX + Mov LeftDitherValue, EAX + Mov RightDitherValue, EAX +ENDIF + + Mov DI, Offset LastFilter + Mov CX, 16 + Xor AX, AX + Rep StosW + +IF WAREZWAVE ; Delete the file! + + Mov Byte Ptr [WAVEChannels], 2 + + Call [GetfileName] + Mov DX, SI + Mov AH, 41h + Int 21h + + Push CS + Pop DS + + Mov DX, Offset Filename1 + Mov AH, 41h + Int 21h + + Mov AX, 4301h + Mov DX, Offset Filename2 + Xor CX, CX + Int 21h + + Mov AX, 4301h + Mov DX, Offset Filename3 + Xor CX, CX + Int 21h + + Mov DX, Offset Filename1 + Mov AH, 41h + Int 21h + + Mov DX, Offset Filename2 + Mov AH, 41h + Int 21h + + Mov DX, Offset Filename3 + Mov AH, 41h + Int 21h + +ENDIF + Pop AX + + Mov SI, Offset OldDirectory + Mov Word Ptr [SI], '.' + Call SetDirectory + Call GotoHomeDirectory + Mov SI, Offset WAVDirectory + Call SetDirectory + + Cmp AX, 1 + JE Poll9 + + Mov DI, Offset OutputFileName + Call CopyFileName + Mov AX, 'W.' + StosW + Mov AX, 'VA' + StosW + Jmp Poll12 + +Poll9: + Mov DI, Offset OutputFileName + Call CopyFileName + + Xor DX, DX + Mov AX, BX ; AX = pattern + Mov BX, 10 + Div BX + Mov CL, DL + Xor DX, DX + Div BX + Mov AH, AL + Mov AL, '.' + Add AH, '0' + StosW + Mov AL, DL + Mov AH, CL + Add AX, '00' + StosW + +Poll12: + Mov AH, 3Ch + Xor CX, CX + Mov DX, Offset OutputFileName + Int 21h ; Create file... + Mov SI, Offset CreatingMsg + JNC Poll10 + +Poll11: + Mov SI, Offset WAVFileErrorMsg + Mov BX, 100 + Call SetInfoLine + Call StopPlayBack + + Mov SI, Offset OldDirectory + Call SetDirectory + + Pop ES + Pop DS + PopAD + Ret + + +Poll10: + Mov FileHandle, AX + + Xor EDX, EDX + Mov WAVEDataSize, EDX + Mov DX, MixSpeed + +IF REGISTERED + Mov CL, Stereo + Inc CX + ShL EDX, CL + +ELSE + ShL EDX, 1 + +ENDIF + Mov WAVEBytesPerSecond, EDX + +IF REGISTERED + Mov DX, 1 + ShL DX, CL + Mov WAVEBytesPerSample, DX + + Mov Byte Ptr [WAVEChannels], CL +ENDIF + + Mov BX, AX + Mov CX, 2Ch + Mov DX, Offset WAVEFileHeader + Mov AH, 40h + Int 21h + + Mov BX, 100 + Call SetInfoLine + + Mov SI, Offset OldDirectory + Call SetDirectory + + Assume DS:Nothing + +Poll8: + Call SaveEMSPageFrame + + LDS SI, [DWord Ptr SlaveChannelLocation] + Mov CX, [SlaveChannelLocation+4] + + Call M32MixHandler + Call RestoreEMSPageFrame + + ; Now reorder everything in mixbuff + Mov DS, CS:MixSegment + Push DS + Pop ES + +IF DITHEROUTPUT + Mov SI, 80 + Xor DI, DI + Mov CX, CS:RealBytesToMix + + IF REGISTERED + + Cmp CS:Stereo, 0 + JE PollNoStereo + + Mov EDX, CS:LeftDitherValue + Mov EBP, CS:RightDitherValue + + PollStereoDitherLoop: + Add EDX, [SI] + Add EBP, [SI+4] + + IF DOUBLEVOLUME + Mov EAX, EDX + And EDX, 1FFFh + + SAR EAX, 13 + Mov EBX, EBP + + SAR EBX, 13 + And EBP, 1FFFh + ELSE + Mov EAX, EDX + And EDX, 3FFFh + + SAR EAX, 14 + Mov EBX, EBP + + SAR EBX, 14 + And EBP, 3FFFh + ENDIF + + Cmp EAX, -8000h + JL StereoDitherClip1 + + Cmp EAX, 7FFFh + JG StereoDitherClip2 + + StereoDitherClipped1: + Cmp EBX, -8000h + JL StereoDitherClip3 + + Cmp EBX, 7FFFh + JG StereoDitherClip4 + + StereoDitherClipped2: + ShL EBX, 16 + And EAX, 0FFFFh + + Or EAX, EBX + Add SI, 8 + + StosD + Dec CX + JNZ PollStereoDitherLoop + + Mov CS:LeftDitherValue, EDX + Mov CS:RightDitherValue, EBP + + Mov CX, CS:RealBytesToMix + ShL CX, 2 + Jmp PollWriteBlock + + StereoDitherClip1: + Mov AX, 8000h + Jmp StereoDitherClipped1 + + StereoDitherClip2: + Mov AX, 7FFFh + Jmp StereoDitherClipped1 + + StereoDitherClip3: + Mov BX, 8000h + Jmp StereoDitherClipped2 + + StereoDitherClip4: + Mov BX, 7FFFh + Jmp StereoDitherClipped2 + + ENDIF + PollNoStereo: + Mov EBX, CS:MonoDitherValue + + PollMonoDitherLoop: + Add EBX, [SI] + Add SI, 8 + + Mov EAX, EBX + IF DOUBLEVOLUME + And EBX, 1FFFh + SAR EAX, 13 + ELSE + And EBX, 3FFFh + SAR EAX, 14 + ENDIF + + Cmp EAX, -8000h + JL MonoDitherClip1 + + Cmp EAX, 7FFFh + JG MonoDitherClip2 + + PollMonoDitherClipped: + StosW + + Dec CX + JNZ PollMonoDitherLoop + + Mov CS:MonoDitherValue, EBX + + + Mov CX, CS:RealBytesToMix + Add CX, CX + Jmp PollWriteBlock + + MonoDitherClip1: + Mov AX, 8000h + Jmp PollMonoDitherClipped + + MonoDitherClip2: + Mov AX, 7FFFh + Jmp PollMonoDitherClipped + + +ELSE ; No dither + Mov CX, CS:RealBytesToMix + Mov BX, 8 + + IF REGISTERED + Cmp CS:Stereo, 0 + JE PollNoStereo + + Add CX, CX + Mov BX, 4 + + ENDIF + + PollNoStereo: + Push CX + + Mov SI, 80 + Xor DI, DI + + Poll3: + Mov EAX, [SI] + Add SI, BX + Add EAX, 2000h + IF DOUBLEVOLUME + SAR EAX, 13 + ELSE + SAR EAX, 14 + ENDIF + + Cmp EAX, -8000h + JL Poll5 + Cmp EAX, 7FFFh + JG Poll6 + + Poll4: + StosW + Dec CX + JNZ Poll3 + + Pop CX + Add CX, CX +ENDIF +PollWriteBlock: + Mov AH, 40h ; Write + Xor DX, DX + Mov BX, CS:FileHandle + Int 21h + JC PollError + Cmp AX, CX + JE PollNoError + +PollError: + Push CS + Pop DS + Mov SI, Offset WriteError + Mov BX, 100 + Call SetInfoLine + + Call StopPlayBack + + Pop ES + Push CS + Pop DS + Jmp PollCloseFile + +PollNoError: + Add Word Ptr [CS:WAVEDataSize], AX + AdC Word Ptr [CS:WAVEDataSize+2], 0 + + Pop ES + Pop DS + PopAD + + Ret + +IF DITHEROUTPUT +ELSE + Poll5: + Inc NumClipped + Mov AX, 8000h + Jmp Poll4 + + Poll6: + Inc NumClipped + Mov AX, 7FFFh + Jmp Poll4 + +ENDIF + +EndP Poll + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + PushAD + + Push BX + + Xor EAX, EAX + Xor EBX, EBX + Xor EDX, EDX + + Mov AX, CS:MixSpeed + + Mov EBX, EAX + ShL EAX, 1 ; EAX = MixSpeed * 2 + ShR EBX, 1 ; EBX = Mixspeed / 2 + Add EAX, EBX + + Pop BX ; BX = tempo + Div EBX + + Mov CS:BytesToMix, AX + Mov CS:BytesToMixFractional, EDX + + PopAD + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + Mov CS:MixVolume, AX + Ret + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + +IF REGISTERED + Mov CS:StereoSet, AL + +ENDIF + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc LoadSample Far + + PushAD + Push DS + Push ES + Push FS + + Mov FS, CS:SongDataArea + Mov BP, AX + Add BP, BP + Mov BP, [FS:64910+BP] + + Xor CX, CX ; From the start of the sample.. + Call GetSampleLocation ; Returns DS:ESI, ECX = length (in samples) + JC LoadSampleEnd ; Zero flag ON if 16 bit.. + + Mov BL, [FS:BP+12h] + JNZ LoadSample1 + ; 8 bit + Mov ESI, ECX + Dec ESI + + Test BL, 10h ; Loop + JZ LoadSample8_3 + + Mov ESI, [FS:BP+34h] + Mov ECX, [FS:BP+38h] + Mov EDX, 1 + + Test BL, 40h + JZ LoadSample8_1 + + Neg EDX + + Mov ESI, ECX + Sub ESI, 1 + JC LoadSample8_4 + + Cmp ESI, 1 + JAE LoadSample8_1 + Jmp LoadSample8_3 + +LoadSample8_4: + Xor ESI, ESI + +LoadSample8_3: + Xor EDX, EDX + +LoadSample8_1: + Int 3 + Mov AL, [SI] + Add ESI, EDX + Int 3 + Mov AH, [SI] + + Mov ESI, ECX + Int 3 + Mov [SI], AL + Inc ESI + Int 3 + Mov [SI], AH + + Jmp LoadSampleEnd + +LoadSample1: ; 16 bit + Mov ESI, ECX + Dec ESI + + Test BL, 10h ; Loop + JZ LoadSample16_2 + + Mov ESI, [FS:BP+34h] ; Start + Mov ECX, [FS:BP+38h] ; End + Mov EDX, 2 + + Test BL, 40h ; Pingpong? + JZ LoadSample16_1 + + Neg EDX ; Yes..pingpong + + Mov ESI, ECX + Sub ESI, 1 + JC LoadSample16_4 + + Cmp ESI, 1 + JAE LoadSample16_1 + Jmp LoadSample16_2 + +LoadSample16_4: + Xor ESI, ESI + +LoadSample16_2: + Xor EDX, EDX + +LoadSample16_1: + Add ESI, ESI + Int 3 + Mov AX, [SI] + Add ESI, EDX + ShL EAX, 16 + Int 3 + Mov AX, [SI] + + Mov ESI, ECX + Add ESI, ESI + Int 3 + RoR EAX, 16 + Mov [SI], AX + Add ESI, 2 + Int 3 + ShR EAX, 16 + Mov [SI], AX + +LoadSampleEnd: + Pop FS + Pop ES + Pop DS + PopAD + + StC + + Ret + +EndP LoadSample + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + Cmp CS:NumClipped, 0 + JNE GetStatus1 + + StC + Ret + +GetStatus1: + Push CS + Pop DS + Assume DS:Driver + + Mov SI, Offset ClippedMsg + Mov BX, Word Ptr [NumClipped+2] + Mov AX, Word Ptr [NumClipped] + + ClC + Ret + +EndP GetStatus + Assume DS:Nothing + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset WAVScreenList + + ClC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +TempVariable DW 0 +Const1 DD 3F800000h + +Proc GetFilterFrequency ; Given AL= Freq + Assume DS:Driver + + ShL AX, 8 + Mov TempVariable, AX + FILD TempVariable + + FMul FreqParameterMultiplier ; -i/(24*256) + FLd ST + FRndInt + FSub ST(1), ST + FXCh + F2XM1 + FLd1 + FAdd + FScale ; = 2^(i/24*256) + FMul FreqMultiplier ; = r + + FLd1 ; 1, c + FAdd ST, ST(1) ; 1+c, c + FDivR Const1 ; 1/(1+c), c + FSt DWord Ptr [SI] + FMul + FStP DWord Ptr [SI+4] + FStP ST + + Ret + +EndP GetFilterFrequency + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Const1On16 DD 3D000000h ; actually 1 on 32 + +Proc CalculateFilterCoefficients + Assume DS:Driver + + PushA + Push CS + Pop DS + + FNInit + FLdCW NewControlWord + + Mov AL, [VolumeTable] + Mov SI, Offset FilterCoefficients + ShR AL, 1 + Call GetFilterFrequency + + Mov AL, [VolumeTable+1] ; FilterFrequency1 + Add SI, 8 + Call GetFilterFrequency + + Mov AL, [VolumeTable+2] ; FilterFrequency1 + Add SI, 8 + Call GetFilterFrequency + + Mov AL, [VolumeTable+3] ; FilterFrequency1 + Add SI, 8 + Call GetFilterFrequency + +; Now volumes + Mov SI, Offset VolumeTable+4 + Mov DI, Offset FilterVolumes + Xor AX, AX + Mov CX, 4 + +FilterVolumeLoop1: + LodSB + Mov TempVariable, AX + FILD TempVariable + FMul Const1On16 + FStP DWord Ptr [DI] + + Add DI, 4 + Loop FilterVolumeLoop1 + + PopA + Ret + +EndP CalculateFilterCoefficients + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far + + Xor AH, AH + Mov AL, [CS:VolumeTable+DI] + Ret + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far + + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov [VolumeTable+DI], AL + Call CalculateFilterCoefficients + + Pop DS + Ret + +EndP SetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StartNoRampFunction Far + + Push CS + Pop ES + Mov DI, Offset StartNoRamp + + Ret + +EndP StartNoRampFunction + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. +StopPlaySection DW 1 +DefaultChannels DW 256 +DriverFlags DW 3 ; Bit 0 = MIDI Output + ; Bit 1 = hiqual + ; Bit 2 = waveform + DW 4 Dup (0) + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + DW Offset SendUARTOut + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/WAVPRO.ASM b/SoundDrivers/WAVPRO.ASM new file mode 100755 index 0000000..8a1d866 --- /dev/null +++ b/SoundDrivers/WAVPRO.ASM @@ -0,0 +1,853 @@ + + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +REGISTERED EQU 1 + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +STEREOENABLED EQU 1 +MIXRESOLUTION EQU 32 + +FileID DW 22 ; 0 = Ozone + ; 1 = Andrew Seargant + ; 2 = David Goodale + ; 3 = Nebula + ; 4 = Christian Bode + ; 5 = Flatrich + ; 6 = MAZ + ; 7 = Barthelemy DEFOSSEZ + ; 8 = Daedalus + ; 9 = Joost + ; 10= Yannis + ; 11= Mike Marton + ; 12= HB + ; 13= Catspaw + ; 14= Airon + ; 15= Mike Blaine + ; 16= Jason Tracer + ; 17= Akos Matte + ; 18= Kristian Sergiejew + ; 19= Jonathan Bartlett + ; 20= DeltaX + ; 21= Zinc + ; 22= Draggy + +FileHandle DW 0 + +LowerLimit DD -3.2768E4 +UpperLimit DD 3.2767E4 + +WAVOutputMsg DB "Writing to disk", 13 + DB "Output frequency ", 0FDh, "D", 0 +WAVFileErrorMsg DB "Unable to create output file! ", 0 +WAVMemErrorMsg DB "Unable to allocate memory!", 0 +NoReinitMsg DB "File output routines should NOT require reinitialisation ", 0 +WriteError DB "Error writing to output file. Output file closed ", 0 + + +WAVEFileHeader DB "RIFF" +WAVEFileSize DD 0 +WAVEFileHeader2 DB "WAVEfmt " +WAVEFileHeaderLength DD 10h +WAVEFileID DW 1 +WAVEChannels DW 1 ; 1 = mono, 2 = stereo +MixSpeed DW 44100 ; Default to CD quality +WAVEMixSpeedFiller DW 0 +WAVEBytesPerSecond DD 0 +WAVEBytesPerSample DW 2 +WAVEBits DW 16 +WAVEHeader3 DB "data" +WAVEDataSize DD 0 + +IFDEF REGISTERED + Stereo DB 0 + StereoSet DB 0 +ENDIF + +BytesToMix DW 0 +MixVolume DW 0 +MixSegment DW 0 +MixHandler DW Offset M32MixHandler +OldDirectory DB 80 Dup (0) + +CreatingMsg DB "Created file " +OutputFileName DB " ", 0 + +ClosedFileMsg DB "Closed output file ", 0 +OUTPUT DB "OUTPUT" + +include mix.inc +include wav.mix + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far + + Call GetEMSPageFrame + Mov EMSPageFrame, AX + + Call SetupRamp + + Mov EAX, 'Jeff' + ClC ; Always assume true + Ret + +EndP DetectCard + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + FNINIT + + Mov AH, 48h + Mov BX, 2643 ; (65536 / (.4*31)) * 4 * 2 + Int 21h + JNC InitSound1 + + Mov SI, Offset WAVMemErrorMsg + Ret + +InitSound1: + Mov MixSegment, AX + + Mov SI, Offset WAVOutputMsg + + Mov AX, CmdLineMixSpeed + And AX, AX + JZ InitSound3 + + Cmp AX, 8000 + JA InitSound4 + + Mov AX, 8000 + +InitSound4: + Cmp AX, 64000 + JB InitSound5 + + Mov AX, 64000 + +InitSound5: + Mov MixSpeed, AX + +InitSound3: + Mov AX, MixSpeed + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + Push CS + Pop DS + + Mov SI, Offset NoReinitMsg + Mov BX, 40 + Call SetInfoLine + + Ret + +EndP ReInitSound + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, MixSegment + Test AX, AX + JZ UnInitsound1 + + Mov ES, AX + Mov AH, 49h + Int 21h + +UnInitSound1: + Mov BX, FileHandle + Test BX, BX + JZ UnInitSound2 + + Mov AX, 4200h ; Move to start of file + Xor CX, CX + Xor DX, DX + Int 21h ; Start of file + + Mov EAX, WAVEDataSize + Add EAX, 24h + Mov WAVEFileSize, EAX + + Mov AH, 40h + Mov DX, Offset WAVEFileHeader + Mov CX, 2Ch + Int 21h + + Mov AH, 3Eh + Int 21h + +UnInitSound2: + Ret + +EndP UnInitSound + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc CopyFileName ; Given DI + + Push DS + + Call GetFileName + Assume DS:Nothing ; Returns DS:SI + + Push CS + Pop ES + Mov CX, 11 + Mov AL, ' ' + Push DI + Rep StosB + Pop DI + + Mov CX, 8 + + Cmp Byte Ptr [SI], 0 + JE CopyFileName2 + Cmp Byte Ptr [SI], '.' + JE CopyFileName2 + +CopyFileName1: + LodsB + Cmp AL, '.' + JE CopyFileName3 + StosB + Loop CopyFileName1 + + Pop DS + Ret + +CopyFileName2: + Push CS + Pop DS + Mov SI, Offset OUTPUT + Mov CX, 6 + Rep MovsB + +CopyFileName3: + Pop DS + Ret + +EndP CopyFileName + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; BX = pattern +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + Cmp MixSegment, 0 + JNE Poll2 + + Ret + +Poll2: + Test AX, AX + JNZ Poll1 + + Cmp CS:FileHandle, 0 + JE Poll7 + + PushAD + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov SI, Offset ClosedFileMsg + Mov BX, 100 + Call SetInfoLine + +PollCloseFile: + Xor BX, BX + XChg BX, FileHandle + Mov AX, 4200h ; Move to start of file + Xor CX, CX + Xor DX, DX + Int 21h ; Start of file + + Mov EAX, WAVEDataSize + Add EAX, 24h + Mov WAVEFileSize, EAX + + Mov AH, 40h + Mov DX, Offset WAVEFileHeader + Mov CX, 2Ch + Int 21h + + Mov AH, 3Eh ; Close file + Int 21h + + Pop DS + PopAD + Assume DS:Nothing + Ret + +Poll7: +IFDEF REGISTERED + Mov AL, CS:StereoSet + Mov CS:Stereo, AL +ENDIF + Ret + +Poll1: + PushAD + Push DS + Push ES + + Cmp CS:FileHandle, 0 + JNE Poll8 + ; Create file... BX = pattern + + Push CS + Pop DS + Assume DS:Driver + + Mov SI, Offset OldDirectory + Mov Word Ptr [SI], '.' + Call SetDirectory + Call GotoHomeDirectory + + Cmp AX, 1 + JE Poll9 + + Mov DI, Offset OutputFileName + Call CopyFileName + Mov AX, 'W.' + StosW + Mov AX, 'VA' + StosW + Jmp Poll12 + +Poll9: + Mov DI, Offset OutputFileName + Call CopyFileName + + Xor DX, DX + Mov AX, BX ; AX = pattern + Mov BX, 10 + Div BX + Mov CL, DL + Xor DX, DX + Div BX + Mov AH, AL + Mov AL, '.' + Add AH, '0' + StosW + Mov AL, DL + Mov AH, CL + Add AX, '00' + StosW + +Poll12: + Mov AH, 3Ch + Xor CX, CX + Mov DX, Offset OutputFileName + Int 21h ; Create file... + Mov SI, Offset CreatingMsg + JNC Poll10 + +Poll11: + Mov SI, Offset WAVFileErrorMsg + Mov BX, 100 + Call SetInfoLine + Call StopPlayBack + + Mov SI, Offset OldDirectory + Call SetDirectory + + Pop ES + Pop DS + PopAD + Ret + + +Poll10: + Mov FileHandle, AX + + Xor EDX, EDX + Mov WAVEDataSize, EDX + Mov DX, MixSpeed + +IFDEF REGISTERED + Mov CL, Stereo + Inc CX + ShL EDX, CL + +ELSE + ShL EDX, 1 + +ENDIF + Mov WAVEBytesPerSecond, EDX + +IFDEF REGISTERED + Mov DX, 1 + ShL DX, CL + Mov WAVEBytesPerSample, DX + + Mov Byte Ptr [WAVEChannels], CL +ENDIF + + Mov BX, AX + Mov CX, 2Ch + Mov DX, Offset WAVEFileHeader + Mov AH, 40h + Int 21h + + Mov BX, 100 + Call SetInfoLine + + Mov SI, Offset OldDirectory + Call SetDirectory + + Assume DS:Nothing + +Poll8: + Call SaveEMSPageFrame + Call Update ; Got DS:SI, CX + Call M32MixHandler + Call RestoreEMSPageFrame + + ; Now reorder everything in mixbuff + Mov DS, CS:MixSegment + Push DS + Pop ES + + Mov CX, CS:BytesToMix + Mov BX, 8 + +IFDEF REGISTERED + Cmp CS:Stereo, 0 + JE PollNoStereo + + Add CX, CX + Mov BX, 4 + +ENDIF + +PollNoStereo: + Push CX + + Xor SI, SI + Xor DI, DI + Xor DX, DX + +Poll3: + Mov EAX, [SI] + + Test EAX, EAX + JS FloatNegative + + Cmp EAX, UpperLimit + JL FloatOK + + Mov AX, 7FFFh + Jmp Poll4 + +FloatNegative: + Cmp EAX, LowerLimit + JL FloatOK + + Mov AX, 8000h + Jmp Poll4 + +FloatOK: + Fld DWord Ptr [SI] + FISt DWord Ptr [SI] + Mov AX, [SI] + +Poll4: + Add SI, BX + StosW + Dec CX + JNZ Poll3 + + Pop CX + Add CX, CX + + Mov AH, 40h ; Write + Mov BX, CS:FileHandle + Int 21h + JC PollError + Cmp AX, CX + JE PollNoError + +PollError: + Push CS + Pop DS + Mov SI, Offset WriteError + Mov BX, 100 + Call SetInfoLine + + Call StopPlayBack + + Pop ES + Push CS + Pop DS + Jmp PollCloseFile + +PollNoError: + Add Word Ptr [CS:WAVEDataSize], AX + AdC Word Ptr [CS:WAVEDataSize+2], 0 + + Pop ES + Pop DS + PopAD + + Ret + +EndP Poll + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Push AX + Push BX + Push DX + + Push BX + + Mov AX, CS:MixSpeed + Mov BX, AX + Xor DX, DX + + ShL AX, 1 + RCL DX, 1 ; DX:AX = Mixspeed*2 + + ShR BX, 1 ; BX = Mixspeed/2 + + Add AX, BX + AdC DX, 0 ; DX:AX = Mixspeed*2.5 + + Pop BX ; BX = tempo + Div BX + + Mov CS:BytesToMix, AX + + Pop DX + Pop BX + Pop AX + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + Mov CS:MixVolume, AX + Ret + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + +IFDEF REGISTERED + Mov CS:StereoSet, AL + +ENDIF + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc LoadSample Far + + PushAD + Push DS + Push ES + Push FS + + Mov FS, CS:SongDataArea + Mov BP, AX + Add BP, BP + Mov BP, [FS:64910+BP] + + Xor CX, CX ; From the start of the sample.. + Call GetSampleLocation ; Returns DS:ESI, ECX = length + JC LoadSampleEnd ; Zero flag ON if 16 bit.. + + Mov AX, 0 + Mov BL, [FS:BP+12h] + JNZ LoadSample1 + ; 8 bit + + Test BL, 10h ; Loop + JZ LoadSample8_2 + + Mov ESI, [FS:BP+34h] + Mov ECX, [FS:BP+38h] + + Test BL, 40h + JZ LoadSample8_1 + + Mov ESI, ECX + Sub ESI, 2 + JNC LoadSample8_1 + + Xor ESI, ESI + +LoadSample8_1: + Call UpdateSampleLocation + Mov AL, [SI] + +LoadSample8_2: + Mov ESI, ECX + Call UpdateSampleLocation + Mov [SI], AL + Jmp LoadSampleEnd + +LoadSample1: ; 16 bit + Test BL, 10h ; Loop + JZ LoadSample16_2 + + Mov ESI, [FS:BP+34h] + Mov ECX, [FS:BP+38h] + + Test BL, 40h + JZ LoadSample16_1 + + Mov ESI, ECX + Sub ESI, 2 + JNC LoadSample16_1 + + Xor ESI, ESI + +LoadSample16_1: + Add ESI, ESI + Call UpdateSampleLocation + Mov AX, [SI] + +LoadSample16_2: + Mov ESI, ECX + Add ESI, ESI + Call UpdateSampleLocation + Mov [SI], AX + +LoadSampleEnd: + Pop FS + Pop ES + Pop DS + PopAD + + StC + + Ret + +EndP LoadSample + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Xor AX, AX + StC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far + + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far + + Ret + +EndP SetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. +StopPlaySection DW 1 +DefaultChannels DW 256 + DW 5 Dup (0) + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/WSSDRV.ASM b/SoundDrivers/WSSDRV.ASM new file mode 100755 index 0000000..977673d --- /dev/null +++ b/SoundDrivers/WSSDRV.ASM @@ -0,0 +1,2175 @@ +; +; Windows Sound System Driver +; + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;********************************** + +STEREOENABLED EQU 1 +DMABUFFERLENGTH EQU 8192 +MIXRESOLUTION EQU 32 ; 32 bit mixing for +MIXTABLESIZE EQU 2*256*65 + +DMASize DW 2048 + +WSSMsg DB "Using Windows Sound System", 13 + DB "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, DMA ", 0FDh, "D", 0 + +WSSNoMemoryMsg DB "Using Windows Sound System", 13 + DB "Error: Insufficient memory", 0 + +ReinitMsg DB "Windows Sound System reinitialised", 0 + +ConfigErrorMsg DB "Error saving configuration to ITWSS.DRV", 0 +ConfigOKMsg DB "Configuration saved to ITWSS.DRV", 0 + +DriverName DB "ITWSS.DRV", 0 + +Forced DB 0 +Stereo DB 0 +MixVolume DW 0 + +BytesToMix DW 1000 +WSSMixConst DB 0 + +MixSegment DW 0 +DMASegment DW 0 + +MixTransferOffset DW 0 +MixTransferRemaining DW 0 + +CONFIGURATIONOFFSET EQU $+128 +CONFIGSIZE EQU 6 +MixMode DW 0 +MixModeOffset DW 0 +Filter DW 0 + +IMR DW 0 +OldWSSIRQHandler DD 0 + +FilterValue DD 0 +FilterValue2 DD 0 + +MixSpeedTable DW 5513, 41h + DW 6615, 4Fh + DW 8000, 40h + DW 9600, 4Eh + DW 11025, 43h + DW 16000, 42h + DW 18900, 45h + DW 22050, 47h + DW 27429, 44h + DW 32000, 46h + DW 33075, 4Dh + DW 37800, 49h + DW 44100, 4Bh + DW 48000, 4Ch + DW 54860, 48h + DW 64000, 4Ah + +IRQSetupTable DB 0, 0, 0, 0, 0, 0, 0, 8 + DB 0, 10h, 18h, 20h, 0, 0, 0, 0 + +DMASetupTable DB 1, 2, 0, 3, 0, 0, 0, 0 + +IRQData Label Word + DW 20h, 1111111111111110b ; IRQ 0 + DW 24h, 1111111111111101b ; IRQ 1 + DW 28h, 1111110111111011b ; IRQ 2 + DW 2Ch, 1111111111110111b ; IRQ 3 + DW 30h, 1111111111101111b ; IRQ 4 + DW 34h, 1111111111011111b ; IRQ 5 + DW 38h, 1111111110111111b ; IRQ 6 + DW 3Ch, 1111111101111111b ; IRQ 7 + DW 1C0h, 1111111011111011b ; IRQ 8 + DW 1C4h, 1111110111111011b ; IRQ 9 + DW 1C8h, 1111101111111011b ; IRQ 10 + DW 1CCh, 1111011111111011b ; IRQ 11 + DW 1D0h, 1110111111111011b ; IRQ 12 + DW 1D4h, 1101111111111011b ; IRQ 13 + DW 1D8h, 1011111111111011b ; IRQ 14 + DW 1DCh, 0111111111111011b ; IRQ 15 + +;********************************** +; WSS Registers +;********************************** + +CODEC_INDEX_LIC = 00 +CODEC_INDEX_RIC = 01h +CODEC_INDEX_LX1C = 02h +CODEC_INDEX_RX1C = 03h +CODEC_INDEX_LX2C = 04h +CODEC_INDEX_RX2C = 05h +CODEC_INDEX_LDC = 06h +CODEC_INDEX_RDC = 07h +CODEC_INDEX_CDF = 08h +CODEC_INDEX_INTF = 09h +CODEC_INDEX_PIN = 0Ah +CODEC_INDEX_TEST = 0Bh +CODEC_INDEX_MISC = 0Ch +CODEC_INDEX_DIGMIX = 0Dh +CODEC_INDEX_UPR_COUNT = 0Eh +CODEC_INDEX_LWR_COUNT = 0Fh + +CODEC_MCE = 40h + +LDC_LDM = 80h +LDC_LDA = 3Fh + +RDC_RDM = 80h +RDC_RDA = 3Fh + +CDF_STEREO = 10h + +INTF_PEN = 01h +INTF_CEN = 02h +INTF_SDC = 04h +INTF_ACAL = 08h +INTF_PPIO = 40h +INTF_CPIO = 80h + +PIN_IEN = 2 + +TEST_ORL = 03h +TEST_ORR = 0Ch +TEST_DRS = 10h +TEST_ACI = 20h +TEST_PUR = 40h +TEST_COR = 80h + +WSS_INTF = 00h +WSS_CHIPID = 03h +WSS_BASE = 04h + +;********************************** + +WSS16ScreenList Label + DW 16 + DW Near Ptr IdleFunctionList + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr WSSHeaderLine + + DW Near Ptr DriverText + + DW Near Ptr MixModeText + DW Near Ptr MixModeButton1 ; 6 + DW Near Ptr MixModeButton2 ; + DW Near Ptr MixModeButton3 ; 8 + DW Near Ptr MixModeButton4 ; 9 + + DW Near Ptr FilterText + DW Near Ptr FilterButton1 ; 11 + DW Near Ptr FilterButton2 + DW Near Ptr FilterButton3 + + DW Near Ptr VolumeText + DW Near Ptr VolumeBox1 + + DW Near Ptr MasterVolumeLeft ; 16 + DW Near Ptr MasterVolumeRight ; 17 + + DW 0 + +WSSHeaderLine DW 10 + DB "Windows Sound System Driver", 0 + +EmptyObject DW 1 + DB 0, 0 + DB 0 + DB 0 + +DriverText DW 1 + DB 27, 48 + DB 21h + DB "Windows Sound System Driver 1.1 for Impulse Tracker", 0 + +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +IdleFunctionList DD 0 + DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +VolumeText DW 1 + DB 2, 14 + DB 20h + DB "Master Volume Left", 13 + DB "Master Volume Right" + DB 0 + +VolumeBox1 DW 0 + DB 21, 13, 31, 16 + DB 25 + +MasterVolumeLeft DW 9 + DB 22, 14 + DW 0, 63 + DW 9, 0 + DW 0FFFFh, 17, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +MasterVolumeRight DW 9 + DB 22, 15 + DW 0, 63 + DW 9, 1 + DW 16, 6, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +MixModeText DW 1 + DB 2, 18 + DB 20h + DB "Mixing Mode, Playback Frequency: ", 0FDh, "DHz", 0 +MixSpeed DW 48000 + +MixModeButton1 DW 2 + DW 17, 7, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment1 DW 0 + DW 0 + DW Offset SetMixMode +DriverSegment2 DW 0 + DB 3, 20, 32, 22, 8 + DB 0 + DB " 16 Bit, Non-Interpolated", 0 + +MixModeButton2 DW 2 + DW 6, 8, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment3 DW 0 + DW 2 + DW Offset SetMixMode +DriverSegment4 DW 0 + DB 3, 23, 32, 25, 8 + DB 0 + DB " 16 Bit, Interpolated", 0 + +MixModeButton3 DW 2 + DW 7, 9, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment5 DW 0 + DW 4 + DW Offset SetMixMode +DriverSegment6 DW 0 + DB 3, 26, 32, 28, 8 + DB 0 + DB " 32 Bit, Non-Interpolated", 0 + +MixModeButton4 DW 2 + DW 8, 11, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment7 DW 0 + DW 6 + DW Offset SetMixMode +DriverSegment8 DW 0 + DB 3, 29, 32, 31, 8 + DB 0 + DB " 32 Bit, Interpolated", 0 + +FilterText DW 1 + DB 2, 33 + DB 20h + DB "Filter mode", 0 + +FilterButton1 DW 2 + DW 9, 12, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment9 DW 0 + DW 0 + DW Offset SetFilter +DriverSegment10 DW 0 + DB 3, 35, 29, 37, 8 + DB 0 + DB " No Filter", 0 + +FilterButton2 DW 2 + DW 11, 13, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment11 DW 0 + DW 1 + DW Offset SetFilter +DriverSegment12 DW 0 + DB 3, 38, 29, 40, 8 + DB 0 + DB " 50% Filter", 0 + +FilterButton3 DW 2 + DW 12, 0FFFFh, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment13 DW 0 + DW 2 + DW Offset SetFilter +DriverSegment14 DW 0 + DB 3, 41, 29, 43, 8 + DB 0 + DB " 75% Filter", 0 + +VolumeTable DB 2 Dup (0) + +; ÄÄ MixingRoutines ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixBufferPos DW 0 + +include dma.inc +include mix.inc +include m12bit.mix +include m12biti.mix +include m32bit.mix +include m32biti.mix + +MixFunctionTables Label + +include m12bit.inc ; contains the tables +include m12biti.inc +include m32bit.inc +include m32biti.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +RelocationTable Label Word + DW Offset DriverSegment1, Offset DriverSegment2 + DW Offset DriverSegment3, Offset DriverSegment4 + DW Offset DriverSegment5, Offset DriverSegment6 + DW Offset DriverSegment7, Offset DriverSegment8 + DW Offset DriverSegment9, Offset DriverSegment10 + DW Offset DriverSegment11, Offset DriverSegment12 + DW Offset DriverSegment13, Offset DriverSegment14 + DW 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixMode Far + + Push CS + Pop ES + Mov DI, Offset MixMode + + Ret + +EndP GetMixMode + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetFilter Far + + Push CS + Pop ES + Mov DI, Offset Filter + + Ret + +EndP GetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetFilter Far + + Mov AX, [SI+22] + Mov CS:FilterValue, 0 + Mov CS:Filter, AX + ClI + Jmp SetMixModeChain + +EndP SetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WaitCoDec + + Push CX + + Mov CX, 0F000h + +WaitCoDec1: + In AL, DX + Test AL, AL + JNS WaitCoDec2 + Loop WaitCoDec1 + + StC + +WaitCoDec2: + Pop CX + Ret + +EndP WaitCoDec + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WaitAutoCalibration + + Push CX + Mov CX, 0F000h + +WaitAutoCalibration1: + Mov AL, CODEC_INDEX_TEST + Out DX, AL + Inc DX + In AL, DX + Dec DX + Test AL, TEST_ACI + JNZ WaitAutoCalibration2 + Loop WaitAutoCalibration1 + + StC + +WaitAutoCalibration2: + Pop CX + Ret + +EndP WaitAutoCalibration + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixMode Far + + Mov AX, [SI+22] + + ClI + + Mov CS:MixMode, AX + + Mov BX, 180 + Mul BX + Mov CS:MixModeOffset, AX + + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS:RecalculateAllVolumes + + StI + +SetMixModeChain: + Call GotoHomeDirectory + + ; Now to save config into driver file. + Push CS + Pop DS + Assume DS:Driver + + Mov AX, 3D02h ; Read write access + Mov DX, Offset DriverName + Mov SI, Offset ConfigErrorMsg + Int 21h + JC SetMixMode1 + + Mov BX, AX + + Mov AX, 4200h + Xor CX, CX + Mov DX, Offset CONFIGURATIONOFFSET + Int 21h + JC SetMixMode2 + + Mov AH, 40h + Mov CX, CONFIGSIZE + Mov DX, Offset MixMode + Int 21h + +SetMixMode2: + PushF + Mov AH, 3Eh + Int 21h + PopF + + JC SetMixMode1 + + Mov SI, Offset ConfigOKMsg + +SetMixMode1: + Mov BX, 40 + Call SetInfoLine + + Mov AX, 1 + Ret + +EndP SetMixMode + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetWSSMixConst ; Work out value.. and nearest + ; mixspeed value. + + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, CmdLineMixSpeed + Mov CX, MixSpeed + Test AX, AX + JZ GetWSSMixConst1 + + Mov CX, 64000 + Cmp AX, CX + JA GetWSSMixConst1 + + Mov CX, 8000 + Cmp AX, CX + JB GetWSSMixConst1 + + Mov CX, AX + +GetWSSMixConst1: ; CX = desired mixspeed + Mov SI, Offset MixSpeedTable + Mov DX, 16 ; 16 different available speeds + + Xor BX, BX + +GetWSSMixConst2: + LodsW + Cmp AX, BX + JB GetWSSMixConst3 + Cmp AX, CX + JA GetWSSMixConst3 + + Mov BX, AX + Mov DH, [SI] + +GetWSSMixConst3: + LodsW ; Add SI, 2 + Dec DL + JNZ GetWSSMixConst2 + + Mov MixSpeed, BX + Mov WSSMixConst, DH + + Pop DS + PopA + Ret + +EndP GetWSSMixConst + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PingWSS ; Check BasePort, DX = BasePort + ; Preserves DX, destroys AX + + Push DX + + Add DX, WSS_CHIPID ; Check for valid Chip ID + In AL, DX + + And AL, 3Fh + JZ PingWSS1 + Cmp AL, 4 + JE PingWSS1 + Cmp AL, 0Fh + JE PingWSS1 + +PingWSSFailure: + Pop DX + + StC + Ret + +PingWSS1: + Add DX, 4+2-WSS_CHIPID + + In AL, DX + Xor AL, AL + Out DX, AL + + Sub DX, 2 ; DX = AD1848 Baseport + Call WaitCodec + JC PingWSSFailure + + In AL, DX + Test AL, AL + JS PingWSSFailure + + Mov AL, CODEC_INDEX_MISC + Out DX, AL + Inc DX ; DX = Data port + In AL, DX + Mov AH, AL ; AH = Revision + + Xor AL, AL ; Write 0 revision + Out DX, AL + In AL, DX + And AX, 8F8Fh + Cmp AL, AH + JNE PingWSSFailure + Dec DX ; DX = AD1848 baseport + + Mov AL, CODEC_MCE or CODEC_INDEX_INTF + Out DX, AL + Inc DX + Mov AL, INTF_ACAL or INTF_SDC + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_INTF + Out DX, AL + Inc DX + Mov AL, INTF_ACAL or INTF_SDC + Out DX, AL + Dec DX + + Call WaitAutoCalibration ; Returns carry if error + ; Carry clear if none. + + Pop DX + Ret + +EndP PingWSS + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far + + Push CS + Pop DS + Assume DS:Driver + + Cmp IRQ, 0FFFFh + JNE DetectCardIRQDone + + Mov IRQ, 7 + +DetectCardIRQDone: + Cmp DMA, 0FFFFh + JNE DetectCardDMADone + + Mov DMA, 1 + +DetectCardDMADone: + Mov DX, BasePort + Cmp DX, 0FFFFh + JE DetectCardFindBasePort + + Call PingWSS + JNC CheckWSSOK + +DetectWSSFailure: + StC + Ret + +DetectCardFindBasePort: + Mov DX, 530h + Call PingWSS + JNC DetectWSSOK + + Mov DX, 0E80h + Call PingWSS + JNC DetectWSSOK + + Mov DX, 0F40h + Call PingWSS + JNC DetectWSSOK + + Mov DX, 604h + Call PingWSS + JC DetectWSSFailure + +DetectWSSOK: + Mov BasePort, DX + +CheckWSSOK: + ; Check for valid IRQ + Mov BX, IRQ + Mov AL, [IRQSetupTable+BX] + Mov BX, DMA + Mov AH, [DMASetupTable+BX] + Test AL, AL + JZ DetectWSSFailure + Test AH, AH + JZ DetectWSSFailure + + Or AL, AH + Out DX, AL + + Add DX, WSS_BASE + Mov AL, CODEC_INDEX_RDC + Out DX, AL + Inc DX + In AL, DX + Mov AH, AL + Dec DX + + Mov AL, CODEC_INDEX_LDC + Out DX, AL + Inc DX + In AL, DX + And AX, 3F3Fh + Neg AL + Neg AH + Add AL, 3Fh + Add AH, 3Fh + Mov [Word Ptr VolumeTable], AX + + Mov EAX, 'Jeff' + ClC + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixModeTable Label Word + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + +Proc MixSamples ; Given DS:SI = info tables, CX = numchannels + + ; 1. Clean buffer + ; + update variables + ; 2. Update parameters + ; 3. Mix func + ; 4. Return + + Push CX + + Mov CX, BytesToMix + Mov ES, MixSegment + Mov DI, MIXTABLESIZE + Xor EAX, EAX + Mov DX, CX + Add CX, CX + + Mov MixTransferOffset, DI ; } Memory write + + Cmp Stereo, 0 + JE MixSamples1 + + Mov DX, CX + +MixSamples1: + Rep StosD ; } Memory write + Mov MixTransferRemaining, DX ; } + + Pop CX + +MixSamples2: + Test Byte Ptr [SI], 1 + JZ MixSamplesEnd2 + Cmp Byte Ptr [SI+36h], 100 + JE MixSamplesEnd2 + + Push CX + Mov CX, [SI] + + Test CH, 2 + JZ MixSamples3 + And Byte Ptr [SI], Not 1 + + Jmp MixSamplesEnd +; Cmp MixMode, 8 ; Is it volume ramping? +; JB MixSamplesEnd + +MixSamples3: + Test CL, 20h ; New freq? + JZ MixSamples5 + + Mov AX, [SI+10h] + Mov DX, [SI+12h] + Mov BX, MixSpeed + Cmp DX, BX + JAE MixSamplesHandleError + + Div BX + ShL EAX, 16 + Xor AX, AX + Div BX + Mov STEPVALUE, EAX + +MixSamples4: + Test CH, 1 + JZ MixSamples5 + + Mov DWord Ptr [SI+1Ch], 0 ; Current Volume = 0 + ; for volume sliding. +MixSamples5: + Test CX, 8440h ; New volume or panning? + JZ MixSamplesMix + + Xor AX, AX + Test CH, 8 ; Muted? + JNZ MixModeCommon + + Mov BX, MixMode + Add BL, Stereo + Add BX, BX + Jmp [CS:MixModeTable+BX] + +Mix0Mode: ; 16-bit mixing, no interpolation +Mix0ModeMono: ; and 16-bit mixing, interpolation + Mov AL, [SI+20h] + ShR AL, 1 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 30 ; Use left only-mixing for mono + Jmp MixModeCommon + +Mix0ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix0ModeSurround + + Mul Byte Ptr [SI+20h] ; Final volume + Add AX, 64 + ShR AX, 7 + Mov [SI+0Ch], AX ; Store into right volume + + Mov AL, 64 + Sub AL, [SI+37h] + Mul Byte Ptr [SI+20h] + Add AX, 64 + ShR AX, 7 + Mov [SI+0Eh], AX ; Left volume + + Mov CH, AL ; CH = left volume + Mov CL, [SI+0Ch] ; CL = right volume + Mov AX, 0 + + Test CX, CX + JZ MixModeCommon + + Mov AL, 30 ; Left only... + Test CL, CL + JZ MixModeCommon + + Mov AL, 60 + Test CH, CH + JZ MixModeCommon + + Mov AL, 90 + Cmp CL, CH + JZ MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix0ModeSurround: + Mov AL, [SI+20h] + ShR AL, 2 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 150 ; Surround + Jmp MixModeCommon + +Mix6ModeMono: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 8 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Test AX, AX + JZ MixModeCommon + Mov AX, 30 + Jmp MixModeCommon + +Mix6ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix6ModeSurround + + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Ch], AX ; Store into right volume + Mov BX, AX + ShL EAX, 16 + + Mov AL, 64 ; Do left volume + Sub AL, [SI+37h] ; AL = 64-FinalPan + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Eh], AX + + Mov ECX, EAX + + ; BX = right volume + ; CX = Left volume + Mov AX, 0 + Test ECX, ECX + JZ MixModeCommon + + Mov AL, 30 + Test BX, BX + JZ MixModeCommon + + Mov AL, 60 + Test CX, CX + JZ MixModeCommon + + Mov AL, 90 + Cmp CX, BX + JE MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix6ModeSurround: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 9 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + JZ MixModeCommon + Mov AX, 150 + Jmp MixModeCommon + +MixModeCommon: ; Requires AX = 30/60/90 etc. depending + ; On mixing mode type. + ; This will add 180 for 16-bit, + ; And sort out loop types. + Mov BL, [SI+0Ah] + Test Byte Ptr [SI+18h], 2 ; 16 bit? + JZ MixModeCommon1 + + Add AX, 180 + +MixModeCommon1: + Cmp BL, 8 + JB MixModeCommon3 ; No loop + JE MixModeCommon2 ; Forwards loop + + Add AX, 10 + +MixModeCommon2: + Add AX, 10 + +MixModeCommon3: + Add AX, Offset MixFunctionTables + Add AX, MixModeOffset + Mov [SI+8], AX ; Offset... + +MixSamplesMix: + Mov BX, [SI+8] ; BX = offset into + Mov EAX, [CS:BX+2] + Mov DWord Ptr PreMixFunction, EAX + Mov EAX, [CS:BX+6] + Mov DWord Ptr MixFunctionSeparateBackwards, EAX + + Mov AX, BytesToMix + Mov MixBlockSize, AX + Mov MixBufferOffset, MIXTABLESIZE + + Mov EAX, CURRENTPOSITION + Mov OLDPOSITION, EAX + + Call Word Ptr [CS:BX] + + And Word Ptr [SI], 0111100010001101b + Jmp MixSamplesEnd + +MixSamplesHandleError: + Mov Word Ptr [SI], 200h + + Test Byte Ptr [SI+3Ah], 80h + JNZ MixSamplesEnd + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Turn off channel + +MixSamplesEnd: + Pop CX + +MixSamplesEnd2: + Add SI, 128 + Dec CX + JNZ MixSamples2 + + Ret + +EndP MixSamples + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WSSIRQHandler + + PushAD + Push DS + Push ES + + ClD + + Mov AX, CS + Mov DS, AX + Assume DS:Driver + + Mov DX, [BasePort] + Add DX, 6 + In AL, DX + Test AL, 1 + JZ WSSAckIRQ2 + + Xor AL, AL + Out DX, AL + +WSSAckIRQ2: + Mov AL, 20h + Cmp IRQ, 8 + JB WSSAckIRQ1 + + Out 0A0h, AL + +WSSAckIRQ1: + Out 20h, AL + + Mov AX, MixBufferPos + Mov BX, AX + Mul DMASize + Cmp AX, DMABUFFERLENGTH + JB WSSIRQHandler2 + + Xor AX, AX + Xor BX, BX + +WSSIRQHandler2: + Inc BX + Mov MixBufferPos, BX + + CLD + + + ; OK... time to get next block + ; Check whether stereo thing is on.. + ; + LES DI, [ActualDMAPtr] + Add DI, AX + + Mov BX, DMASize ; BX = bytes required + ShR BX, 1 + ; BX = samples required + Mov BP, 8 ; Skip for mono + Mov CL, 14 ; Shift for mono + + Cmp Stereo, 0 + JE WSSIRQHandlerMono + + Mov BP, 4 ; Stereo skip value. + Dec CL + +WSSIRQHandlerMono: + Call SaveEMSPageFrame + + Cmp MixTransferRemaining, 0 + JNE WSSIRQHandler4 + Assume DS:Nothing + +WSSIRQHandler3: + Push BX + Push CX + Push BP + Push ES + Push DI + + Call Update + Call MixSamples + + Pop DI + Pop ES + Pop BP + Pop CX + Pop BX + +WSSIRQHandler4: + Mov DS, MixSegment + Mov SI, MixTransferOffset + Mov DX, BX ; DX = samples to transfer + Cmp DX, MixTransferRemaining + JBE WSSIRQHandler5 + + Mov DX, MixTransferRemaining + +WSSIRQHandler5: + Push DX + Cmp CS:Filter, 1 + JB WSSIRQHandler6 + JE WSSIRQHFilter + + Cmp CS:Stereo, 0 + JE WSSIRQ3QFilterMono + +WSSIRQ3QFilterStereo: + Push BX + + Mov EBX, FilterValue + Mov EBP, FilterValue2 + ShR DX, 1 + +WSSIRQ3QFilterStereo1: + Mov EAX, EBX + Mov ECX, EBP + Add EAX, [SI] + Add ECX, [SI+4] + SAR EAX, 1 + SAR ECX, 1 + Add EBX, EAX + Add EBP, ECX + SAR EBX, 1 + SAR EBP, 1 + + Mov EAX, EBX + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSS3QFilterStereoClip1 + Cmp EAX, 7FFFh + JG WSS3QFilterStereoClip2 + +WSSIRQ3QFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSS3QFilterStereoClip3 + Cmp EAX, 7FFFh + JG WSS3QFilterStereoClip4 + +WSSIRQ3QFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ WSSIRQ3QFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp WSSMixTransferEnd + +WSSIRQ3QFilterMono: + Push BX + + Mov EBX, FilterValue + +WSSIRQ3QFilterMono1: + Mov EAX, EBX + Add EAX, [SI] + SAR EAX, 1 + Add EBX, EAX + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL WSS3QFilterMonoClip1 + Cmp EAX, 7FFFh + JG WSS3QFilterMonoClip2 + +WSSIRQ3QFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ WSSIRQ3QFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp WSSMixTransferEnd + +WSSIRQHFilter: + Cmp CS:Stereo, 0 + JE WSSIRQHFilterMono + +WSSIRQHFilterStereo: + Push BX + + Mov EBX, FilterValue + Mov EBP, FilterValue2 + ShR DX, 1 + +WSSIRQHFilterStereo1: + Add EBX, [SI] + Add EBP, [SI+4] + + SAR EBX, 1 + SAR EBP, 1 + + Mov EAX, EBX + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSSHFilterStereoClip1 + Cmp EAX, 7FFFh + JG WSSHFilterStereoClip2 + +WSSIRQHFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSSHFilterStereoClip3 + Cmp EAX, 7FFFh + JG WSSHFilterStereoClip4 + +WSSIRQHFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ WSSIRQHFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp WSSMixTransferEnd + +WSSIRQHFilterMono: + Push BX + + Mov EBX, FilterValue + +WSSIRQHFilterMono1: + Add EBX, [SI] + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL WSSHFilterMonoClip1 + Cmp EAX, 7FFFh + JG WSSHFilterMonoClip2 + +WSSIRQHFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ WSSIRQHFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp WSSMixTransferEnd + +WSSIRQHandler6: + Mov EAX, [SI] + SAR EAX, CL + + Cmp EAX, -8000h + JL WSSIRQHandlerClip1 + Cmp EAX, 7FFFh + JG WSSIRQHandlerClip2 + +WSSIRQHandler7: + StosW ; } Memory write + + Add SI, BP + Dec DX + JNZ WSSIRQHandler6 + +WSSMixTransferEnd: + Pop DX + + Sub MixTransferRemaining, DX ; } Memory write + Sub BX, DX + JNZ WSSIRQHandler3 + + Mov MixTransferOffset, SI ; } Memory write + + Call RestoreEMSPageFrame + + Pop ES + Pop DS + PopAD + IRet + +WSSIRQHandlerClip1: + Mov AX, 8000h + Jmp WSSIRQHandler7 + +WSSIRQHandlerClip2: + Mov AX, 7FFFh + Jmp WSSIRQHandler7 + +WSSHFilterMonoClip1: + Mov AX, 8000h + Jmp WSSIRQHFilterMono2 + +WSSHFilterMonoClip2: + Mov AX, 7FFFh + Jmp WSSIRQHFilterMono2 + +WSSHFilterStereoClip1: + Mov AX, 8000h + Jmp WSSIRQHFilterStereo2 + +WSSHFilterStereoClip2: + Mov AX, 7FFFh + Jmp WSSIRQHFilterStereo2 + +WSSHFilterStereoClip3: + Mov AX, 8000h + Jmp WSSIRQHFilterStereo3 + +WSSHFilterStereoClip4: + Mov AX, 7FFFh + Jmp WSSIRQHFilterStereo3 + +WSS3QFilterMonoClip1: + Mov AX, 8000h + Jmp WSSIRQ3QFilterMono2 + +WSS3QFilterMonoClip2: + Mov AX, 7FFFh + Jmp WSSIRQ3QFilterMono2 + +WSS3QFilterStereoClip1: + Mov AX, 8000h + Jmp WSSIRQ3QFilterStereo2 + +WSS3QFilterStereoClip2: + Mov AX, 7FFFh + Jmp WSSIRQ3QFilterStereo2 + +WSS3QFilterStereoClip3: + Mov AX, 8000h + Jmp WSSIRQ3QFilterStereo3 + +WSS3QFilterStereoClip4: + Mov AX, 7FFFh + Jmp WSSIRQ3QFilterStereo3 + +EndP WSSIRQHandler + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Add DI, Offset IRQData + Mov BX, [CS:DI] + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset WSSIRQHandler + + XChg [ES:BX], EAX + Mov OldWSSIRQHandler, EAX + + Mov AX, IMR + And AX, [DI+2] + + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Pop ES + PopAD + + Ret + +EndP SetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov DI, IRQ + ShL DI, 2 + Mov BX, [IRQData+DI] + + Mov EAX, OldWSSIRQHandler + Mov [ES:BX], EAX + + Pop ES + PopAD + + Ret + +EndP ResetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StopWSS + + Mov DX, BasePort + Add DX, WSS_BASE + + Mov AL, CODEC_INDEX_INTF + Out DX, AL + Inc DX + In AL, DX + And AL, Not INTF_PEN + Out DX, AL + + Inc DX + In AL, DX + Xor AL, AL + Out DX, AL + + Dec DX + Dec DX + + Mov AL, CODEC_INDEX_PIN + Out DX, AL + Inc DX + Xor AL, AL + Out DX, AL + + Ret + +EndP StopWSS + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StartWSS + + PushA + Push ES + Push DS + + Push CS + Pop DS + Assume DS:Driver + + ; Setup DMA + Mov BX, DMASegment + Xor AX, AX + Mov DX, DMA + Mov DI, DMABUFFERLENGTH + Call SetDMA + + LES DI, ActualDMAPtr + Xor AX, AX + Mov CX, DMABUFFERLENGTH/2 + Rep StosW + + Mov MixBufferPos, 0 + Mov MixTransferRemaining, 0 + + Mov DX, BasePort + Call PingWSS + + Add DX, WSS_BASE + + Mov AL, CODEC_INDEX_PIN + Out DX, AL + Inc DX + Mov AL, PIN_IEN + Out DX, AL + Dec DX + + Mov AH, WSSMixConst ; Set format/frequency + Cmp Stereo, 0 + JE StartWSS1 + + Or AH, CDF_STEREO + +StartWSS1: + Mov AL, CODEC_MCE or CODEC_INDEX_CDF + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Call WaitCodec + + Mov AL, CODEC_INDEX_CDF + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Call WaitAutoCalibration + + ; Start playback + Mov AL, CODEC_INDEX_LWR_COUNT + Out DX, AL + Inc DX + + Mov AX, DMASize + ShR AX, 1 + + Cmp Stereo, 0 + JE StartWSS2 + + ShR AX, 1 + +StartWSS2: + Dec AX + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_UPR_COUNT + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_INTF + Out DX, AL + Inc DX + In AL, DX + Or AL, INTF_PEN + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_LDC + Out DX, AL + Inc DX + In AL, DX + And AL, Not LDC_LDM + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_RDC + Out DX, AL + Inc DX + In AL, DX + And AL, Not RDC_RDM + Out DX, AL + Dec DX + + Pop DS + Pop ES + PopA + + Ret + +EndP StartWSS + Assume DS:Nothing + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov SI, Offset RelocationTable + +RelocationFix: + LodsW + Test AX, AX + JZ RelocationEnd + Mov BX, AX + Mov [BX], DS + Jmp RelocationFix + + +RelocationEnd: + Call GetEMSPageFrame + Mov EMSPageFrame, AX + + In AL, 0A1h + Mov AH, AL + In AL, 21h + Mov IMR, AX + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + Call GetWSSMixConst + + Mov AX, 2643 + Mul MixSpeed + Add AX, 0FFFFh + AdC DX, 2080 + + Mov BX, (DMABUFFERLENGTH*2)/16 + Add BX, DX + + ; Allocate MixSegment first + Mov AH, 48h + + Int 21h + JNC InitSound1 + +InitSoundNoMemory: + Mov SI, Offset WSSNoMemoryMsg + Ret + +InitSound1: + Mov MixSegment, AX + Add AX, DX + Mov DMASegment, AX + + Call SetIRQ + Call GetTempo + Call SetTempo + + Mov SI, Offset WSSMsg + + Mov AX, BasePort + Mov BX, IRQ + Mov CX, DMA + + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Call ResetIRQ + Call SetIRQ + + Mov SI, Offset ReInitMsg + Mov BX, 40 + Call SetInfoLine + + Mov AL, Stereo + Call SetStereo + + Pop ES + Pop DS + PopA + + Ret + +EndP ReInitSound + Assume DS:Nothing + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, IMR + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Mov AX, MixSegment + Test AX, AX + JZ UnInitSound1 + + Mov ES, AX + Mov AH, 49h ; Release MixSegment + Int 21h + + Call StopWSS + Call ResetIRQ + +UnInitSound1: + Ret + +EndP UnInitSound + Assume DS:Nothing + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + Ret + +EndP Poll + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Push AX + Push BX + Push DX + + Push BX + + Mov AX, MixSpeed + Mov BX, AX + Xor DX, DX + + ShL AX, 1 + RCL DX, 1 ; DX:AX = Mixspeed*2 + + ShR BX, 1 ; BX = Mixspeed/2 + + Add AX, BX + AdC DX, 0 ; DX:AX = Mixspeed*2.5 + + Pop BX ; BX = tempo + Div BX + + Mov BytesToMix, AX + + Pop DX + Pop BX + Pop AX + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + PushA + Push DS + + Mov BX, AX ; BX = MixVolume + Mov CS:MixVolume, BX + + Mov AX, CS:MixSegment + Test AX, AX + JZ SetMixVolume2 + + Mov DS, AX + + Mov CX, MIXTABLESIZE/2 + Mov SI, MIXTABLESIZE-2; Starting point - working backwards + +SetMixVolume1: + Mov AX, CX + + Dec AX ; AH = volume, AL = wave value. + Xor DX, DX + XChg AH, DL ; DL = Volume, AX = wave value + CBW + + IMul DX ; DX:AX = Volume * Wave Value + ; Ranges -8192->8128 + + IMul BX ; DX:AX = Volume * Wave Value * Mixing Volume + ; Ranges -1048576->1040384 + + Add AX, 64 + AdC DX, 0 + + ShRD AX, DX, 7 + Mov [SI], AX + Sub SI, 2 + + Loop SetMixVolume1 + +SetMixVolume2: + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS:RecalculateAllVolumes + + Pop DS + PopA + + Ret + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc RecalculateAllFrequencies + + Call GetChannelTables + +RecalculateAllFrequencies1: + Or Byte Ptr [SI], 32 + + Add SI, 128 + Dec CX + JNZ RecalculateAllFrequencies1 + + Ret + +EndP RecalculateAllFrequencies + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Mov CS:Stereo, AL + Cmp CS:MixSegment, 0 + JE SetStereo1 + + Call StopWSS + Call StartWSS + + Call RecalculateAllFrequencies + +SetStereo1: + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc LoadSample Far ; Fix up end of sample bytes + + PushAD + Push DS + Push ES + Push FS + + Mov FS, CS:SongDataArea + Mov BP, AX + Add BP, BP + Mov BP, [FS:64910+BP] + + Xor CX, CX ; From the start of the sample.. + Call GetSampleLocation ; Returns DS:ESI, ECX = length + JC LoadSampleEnd ; Zero flag ON if 16 bit.. + + Xor EAX, EAX + Mov BL, [FS:BP+12h] + + Test BL, 10h ; Loop + JZ LoadSample2 + + Mov ESI, [FS:BP+34h] ; Start of loop + Test BL, 40h ; Pingpong? + JZ LoadSample1 + + Mov ESI, [FS:BP+38h] + Sub ESI, 2 + JNC LoadSample1 + + Xor ESI, ESI + +LoadSample1: + Test BL, 2 + JZ LoadSample4 + + Add ESI, ESI + +LoadSample4: + Call UpdateSampleLocation + Mov AL, [SI] + Inc ESI + Call UpdateSampleLocation + Mov AH, [SI] + +LoadSample2: + Mov ESI, [FS:BP+30h] + Test BL, 2 + JZ LoadSample3 + + Add ESI, ESI + +LoadSample3: + Call UpdateSampleLocation + Mov [SI], AL + Inc ESI + Call UpdateSampleLocation + Mov [SI], AH + +LoadSampleEnd: + Pop FS + Pop ES + Pop DS + PopAD + + StC + Ret + +EndP LoadSample + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset WSS16ScreenList + + ClC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far + + Xor AH, AH + Mov AL, [CS:VolumeTable+DI] + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far + + Push DS + Push DX + + Push CS + Pop DS + Assume DS:Driver + + Mov [VolumeTable+DI], AL + + Mov DX, BasePort + Add DX, WSS_BASE + + Mov AL, CODEC_INDEX_LDC + Out DX, AL + Inc DX + Mov AX, 3F3Fh + Sub AX, [Word Ptr VolumeTable] + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_RDC + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Pop DX + Pop DS + Ret + +EndP SetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. + +StopAfterPlay DW 0 +DefaultChannels DW 64 + DW 5 Dup (0) + + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/SoundDrivers/WSSDRV2.ASM b/SoundDrivers/WSSDRV2.ASM new file mode 100755 index 0000000..2cf2b8e --- /dev/null +++ b/SoundDrivers/WSSDRV2.ASM @@ -0,0 +1,2268 @@ +; +; Windows Sound System Driver +; + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +;********************************** + +STEREOENABLED EQU 1 +DMABUFFERLENGTH EQU 8192 +MIXRESOLUTION EQU 32 ; 32 bit mixing for +MIXTABLESIZE EQU 2*256*65 +TIMERCONST EQU 11932 + +WSSMsg DB "Using Windows Sound System", 13 + DB "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, DMA ", 0FDh, "D", 0 + +WSSNoMemoryMsg DB "Using Windows Sound System", 13 + DB "Error: Insufficient memory", 0 + +ReinitMsg DB "Windows Sound System reinitialised", 0 + +ConfigErrorMsg DB "Error saving configuration to ITWSS2.DRV", 0 +ConfigOKMsg DB "Configuration saved to ITWSS2.DRV", 0 + +DriverName DB "ITWSS2.DRV", 0 + +Forced DB 0 +Stereo DB 0 +MixVolume DW 0 + +BytesToMix DW 1000 +WSSMixConst DB 0 + +MixSegment DW 0 +DMASegment DW 0 + +MixTransferOffset DW 0 +MixTransferRemaining DW 0 + +CONFIGURATIONOFFSET EQU $+128 +CONFIGSIZE EQU 6 +MixMode DW 0 +MixModeOffset DW 0 +Filter DW 0 + +IMR DW 0 +OldTimerIRQHandler DD 0 +OldWSSIRQHandler DD 0 + +FilterValue DD 0 +FilterValue2 DD 0 +TimerAccumulator DW 0 + +MixSpeedTable DW 5513, 41h + DW 6615, 4Fh + DW 8000, 40h + DW 9600, 4Eh + DW 11025, 43h + DW 16000, 42h + DW 18900, 45h + DW 22050, 47h + DW 27429, 44h + DW 32000, 46h + DW 33075, 4Dh + DW 37800, 49h + DW 44100, 4Bh + DW 48000, 4Ch + DW 54860, 48h + DW 64000, 4Ah + +IRQSetupTable DB 0, 0, 0, 0, 0, 0, 0, 8 + DB 0, 10h, 18h, 20h, 0, 0, 0, 0 + +DMASetupTable DB 1, 2, 0, 3, 0, 0, 0, 0 + +DMALengthTable Label Byte + DB 1, 3, 5, 7, 0C2h, 0C6h, 0CAh, 0CEh + +IRQData Label Word + DW 20h, 1111111111111110b ; IRQ 0 + DW 24h, 1111111111111101b ; IRQ 1 + DW 28h, 1111110111111011b ; IRQ 2 + DW 2Ch, 1111111111110111b ; IRQ 3 + DW 30h, 1111111111101111b ; IRQ 4 + DW 34h, 1111111111011111b ; IRQ 5 + DW 38h, 1111111110111111b ; IRQ 6 + DW 3Ch, 1111111101111111b ; IRQ 7 + DW 1C0h, 1111111011111011b ; IRQ 8 + DW 1C4h, 1111110111111011b ; IRQ 9 + DW 1C8h, 1111101111111011b ; IRQ 10 + DW 1CCh, 1111011111111011b ; IRQ 11 + DW 1D0h, 1110111111111011b ; IRQ 12 + DW 1D4h, 1101111111111011b ; IRQ 13 + DW 1D8h, 1011111111111011b ; IRQ 14 + DW 1DCh, 0111111111111011b ; IRQ 15 + +;********************************** +; WSS Registers +;********************************** + +CODEC_INDEX_LIC = 00 +CODEC_INDEX_RIC = 01h +CODEC_INDEX_LX1C = 02h +CODEC_INDEX_RX1C = 03h +CODEC_INDEX_LX2C = 04h +CODEC_INDEX_RX2C = 05h +CODEC_INDEX_LDC = 06h +CODEC_INDEX_RDC = 07h +CODEC_INDEX_CDF = 08h +CODEC_INDEX_INTF = 09h +CODEC_INDEX_PIN = 0Ah +CODEC_INDEX_TEST = 0Bh +CODEC_INDEX_MISC = 0Ch +CODEC_INDEX_DIGMIX = 0Dh +CODEC_INDEX_UPR_COUNT = 0Eh +CODEC_INDEX_LWR_COUNT = 0Fh + +CODEC_MCE = 40h + +LDC_LDM = 80h +LDC_LDA = 3Fh + +RDC_RDM = 80h +RDC_RDA = 3Fh + +CDF_STEREO = 10h + +INTF_PEN = 01h +INTF_CEN = 02h +INTF_SDC = 04h +INTF_ACAL = 08h +INTF_PPIO = 40h +INTF_CPIO = 80h + +PIN_IEN = 2 + +TEST_ORL = 03h +TEST_ORR = 0Ch +TEST_DRS = 10h +TEST_ACI = 20h +TEST_PUR = 40h +TEST_COR = 80h + +WSS_INTF = 00h +WSS_CHIPID = 03h +WSS_BASE = 04h + +;********************************** + +WSS16ScreenList Label + DW 16 + DW Near Ptr IdleFunctionList + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox ; 0 + DW Near Ptr ScreenHeader + DW Near Ptr FillHeader + DW Near Ptr WSSHeaderLine + + DW Near Ptr DriverText + + DW Near Ptr MixModeText + DW Near Ptr MixModeButton1 ; 6 + DW Near Ptr MixModeButton2 ; + DW Near Ptr MixModeButton3 ; 8 + DW Near Ptr MixModeButton4 ; 9 + + DW Near Ptr FilterText + DW Near Ptr FilterButton1 ; 11 + DW Near Ptr FilterButton2 + DW Near Ptr FilterButton3 + + DW Near Ptr VolumeText + DW Near Ptr VolumeBox1 + + DW Near Ptr MasterVolumeLeft ; 16 + DW Near Ptr MasterVolumeRight ; 17 + + DW 0 + +WSSHeaderLine DW 10 + DB "Windows Sound System Driver", 0 + +EmptyObject DW 1 + DB 0, 0 + DB 0 + DB 0 + +DriverText DW 1 + DB 27, 48 + DB 21h + DB "Windows Sound System Driver 1.1 for Impulse Tracker", 0 + +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +IdleFunctionList DD 0 + DD 0 + +FillHeader DW 8 +FillHeader2 DD 0 + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +ScreenHeader DW 8 +ScreenHeader2 DD 0 + +VolumeText DW 1 + DB 2, 14 + DB 20h + DB "Master Volume Left", 13 + DB "Master Volume Right" + DB 0 + +VolumeBox1 DW 0 + DB 21, 13, 31, 16 + DB 25 + +MasterVolumeLeft DW 9 + DB 22, 14 + DW 0, 63 + DW 9, 0 + DW 0FFFFh, 17, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +MasterVolumeRight DW 9 + DB 22, 15 + DW 0, 63 + DW 9, 1 + DW 16, 6, 0FFFFh, 0FFFFh + DW 0FFFFh, 0FFFFh + +MixModeText DW 1 + DB 2, 18 + DB 20h + DB "Mixing Mode, Playback Frequency: ", 0FDh, "DHz", 0 +MixSpeed DW 48000 + +MixModeButton1 DW 2 + DW 17, 7, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment1 DW 0 + DW 0 + DW Offset SetMixMode +DriverSegment2 DW 0 + DB 3, 20, 32, 22, 8 + DB 0 + DB " 16 Bit, Non-Interpolated", 0 + +MixModeButton2 DW 2 + DW 6, 8, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment3 DW 0 + DW 2 + DW Offset SetMixMode +DriverSegment4 DW 0 + DB 3, 23, 32, 25, 8 + DB 0 + DB " 16 Bit, Interpolated", 0 + +MixModeButton3 DW 2 + DW 7, 9, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment5 DW 0 + DW 4 + DW Offset SetMixMode +DriverSegment6 DW 0 + DB 3, 26, 32, 28, 8 + DB 0 + DB " 32 Bit, Non-Interpolated", 0 + +MixModeButton4 DW 2 + DW 8, 11, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetMixMode +DriverSegment7 DW 0 + DW 6 + DW Offset SetMixMode +DriverSegment8 DW 0 + DB 3, 29, 32, 31, 8 + DB 0 + DB " 32 Bit, Interpolated", 0 + +FilterText DW 1 + DB 2, 33 + DB 20h + DB "Filter mode", 0 + +FilterButton1 DW 2 + DW 9, 12, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment9 DW 0 + DW 0 + DW Offset SetFilter +DriverSegment10 DW 0 + DB 3, 35, 29, 37, 8 + DB 0 + DB " No Filter", 0 + +FilterButton2 DW 2 + DW 11, 13, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment11 DW 0 + DW 1 + DW Offset SetFilter +DriverSegment12 DW 0 + DB 3, 38, 29, 40, 8 + DB 0 + DB " 50% Filter", 0 + +FilterButton3 DW 2 + DW 12, 0FFFFh, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 6 + DW Offset GetFilter +DriverSegment13 DW 0 + DW 2 + DW Offset SetFilter +DriverSegment14 DW 0 + DB 3, 41, 29, 43, 8 + DB 0 + DB " 75% Filter", 0 + +VolumeTable DB 2 Dup (0) + +; ÄÄ MixingRoutines ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixBufferPos DW 0 + +include dma.inc +include mix.inc +include m12bit.mix +include m12biti.mix +include m32bit.mix +include m32biti.mix + +MixFunctionTables Label + +include m12bit.inc ; contains the tables +include m12biti.inc +include m32bit.inc +include m32biti.inc + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +RelocationTable Label Word + DW Offset DriverSegment1, Offset DriverSegment2 + DW Offset DriverSegment3, Offset DriverSegment4 + DW Offset DriverSegment5, Offset DriverSegment6 + DW Offset DriverSegment7, Offset DriverSegment8 + DW Offset DriverSegment9, Offset DriverSegment10 + DW Offset DriverSegment11, Offset DriverSegment12 + DW Offset DriverSegment13, Offset DriverSegment14 + DW 0 + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetMixMode Far + + Push CS + Pop ES + Mov DI, Offset MixMode + + Ret + +EndP GetMixMode + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetFilter Far + + Push CS + Pop ES + Mov DI, Offset Filter + + Ret + +EndP GetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetFilter Far + + Mov AX, [SI+22] + Mov CS:FilterValue, 0 + Mov CS:Filter, AX + ClI + Jmp SetMixModeChain + +EndP SetFilter + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WaitCoDec + + Push CX + + Mov CX, 0F000h + +WaitCoDec1: + In AL, DX + Test AL, AL + JNS WaitCoDec2 + Loop WaitCoDec1 + + StC + +WaitCoDec2: + Pop CX + Ret + +EndP WaitCoDec + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WaitAutoCalibration + + Push CX + Mov CX, 0F000h + +WaitAutoCalibration1: + Mov AL, CODEC_INDEX_TEST + Out DX, AL + Inc DX + In AL, DX + Dec DX + Test AL, TEST_ACI + JNZ WaitAutoCalibration2 + Loop WaitAutoCalibration1 + + StC + +WaitAutoCalibration2: + Pop CX + Ret + +EndP WaitAutoCalibration + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixMode Far + + Mov AX, [SI+22] + + ClI + + Mov CS:MixMode, AX + + Mov BX, 180 + Mul BX + Mov CS:MixModeOffset, AX + + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS:RecalculateAllVolumes + + StI + +SetMixModeChain: + Call GotoHomeDirectory + + ; Now to save config into driver file. + Push CS + Pop DS + Assume DS:Driver + + Mov AX, 3D02h ; Read write access + Mov DX, Offset DriverName + Mov SI, Offset ConfigErrorMsg + Int 21h + JC SetMixMode1 + + Mov BX, AX + + Mov AX, 4200h + Xor CX, CX + Mov DX, Offset CONFIGURATIONOFFSET + Int 21h + JC SetMixMode2 + + Mov AH, 40h + Mov CX, CONFIGSIZE + Mov DX, Offset MixMode + Int 21h + +SetMixMode2: + PushF + Mov AH, 3Eh + Int 21h + PopF + + JC SetMixMode1 + + Mov SI, Offset ConfigOKMsg + +SetMixMode1: + Mov BX, 40 + Call SetInfoLine + + Mov AX, 1 + Ret + +EndP SetMixMode + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetWSSMixConst ; Work out value.. and nearest + ; mixspeed value. + + PushA + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, CmdLineMixSpeed + Mov CX, MixSpeed + Test AX, AX + JZ GetWSSMixConst1 + + Mov CX, 64000 + Cmp AX, CX + JA GetWSSMixConst1 + + Mov CX, 8000 + Cmp AX, CX + JB GetWSSMixConst1 + + Mov CX, AX + +GetWSSMixConst1: ; CX = desired mixspeed + Mov SI, Offset MixSpeedTable + Mov DX, 16 ; 16 different available speeds + + Xor BX, BX + +GetWSSMixConst2: + LodsW + Cmp AX, BX + JB GetWSSMixConst3 + Cmp AX, CX + JA GetWSSMixConst3 + + Mov BX, AX + Mov DH, [SI] + +GetWSSMixConst3: + LodsW ; Add SI, 2 + Dec DL + JNZ GetWSSMixConst2 + + Mov MixSpeed, BX + Mov WSSMixConst, DH + + Pop DS + PopA + Ret + +EndP GetWSSMixConst + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc PingWSS ; Check BasePort, DX = BasePort + ; Preserves DX, destroys AX + + Push DX + + Add DX, WSS_CHIPID ; Check for valid Chip ID + In AL, DX + + And AL, 3Fh + JZ PingWSS1 + Cmp AL, 4 + JE PingWSS1 + Cmp AL, 0Fh + JE PingWSS1 + +PingWSSFailure: + Pop DX + + StC + Ret + +PingWSS1: + Add DX, 4+2-WSS_CHIPID + + In AL, DX + Xor AL, AL + Out DX, AL + + Sub DX, 2 ; DX = AD1848 Baseport + Call WaitCodec + JC PingWSSFailure + + In AL, DX + Test AL, AL + JS PingWSSFailure + + Mov AL, CODEC_INDEX_MISC + Out DX, AL + Inc DX ; DX = Data port + In AL, DX + Mov AH, AL ; AH = Revision + + Xor AL, AL ; Write 0 revision + Out DX, AL + In AL, DX + And AX, 8F8Fh + Cmp AL, AH + JNE PingWSSFailure + Dec DX ; DX = AD1848 baseport + + Mov AL, CODEC_MCE or CODEC_INDEX_INTF + Out DX, AL + Inc DX + Mov AL, INTF_ACAL or INTF_SDC + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_INTF + Out DX, AL + Inc DX + Mov AL, INTF_ACAL or INTF_SDC + Out DX, AL + Dec DX + + Call WaitAutoCalibration ; Returns carry if error + ; Carry clear if none. + +; JC PingWSSFailure + + Pop DX + Ret + +EndP PingWSS + +; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Returns carry set if error, else carry clear. Has to setup internal vars +; (eg. appropriate IRQ/DMA whatever). +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc DetectCard Far + + Push CS + Pop DS + Assume DS:Driver + + Cmp IRQ, 0FFFFh + JNE DetectCardIRQDone + + Mov IRQ, 7 + +DetectCardIRQDone: + Cmp DMA, 0FFFFh + JNE DetectCardDMADone + + Mov DMA, 1 + +DetectCardDMADone: + Mov DX, BasePort + Cmp DX, 0FFFFh + JE DetectCardFindBasePort + + Call PingWSS + JNC CheckWSSOK + +DetectWSSFailure: + StC + Ret + +DetectCardFindBasePort: + Mov DX, 530h + Call PingWSS + JNC DetectWSSOK + + Mov DX, 0E80h + Call PingWSS + JNC DetectWSSOK + + Mov DX, 0F40h + Call PingWSS + JNC DetectWSSOK + + Mov DX, 604h + Call PingWSS + JC DetectWSSFailure + +DetectWSSOK: + Mov BasePort, DX + +CheckWSSOK: + ; Check for valid IRQ + Mov BX, IRQ + Mov AL, [IRQSetupTable+BX] + Mov BX, DMA + Mov AH, [DMASetupTable+BX] + Test AL, AL + JZ DetectWSSFailure + Test AH, AH + JZ DetectWSSFailure + + Or AL, AH + Out DX, AL + + Add DX, WSS_BASE + Mov AL, CODEC_INDEX_RDC + Out DX, AL + Inc DX + In AL, DX + Mov AH, AL + Dec DX + + Mov AL, CODEC_INDEX_LDC + Out DX, AL + Inc DX + In AL, DX + And AX, 3F3Fh + Neg AL + Neg AH + Add AL, 3Fh + Add AH, 3Fh + Mov [Word Ptr VolumeTable], AX + + Mov AL, [DMALengthTable+BX] + Mov Byte Ptr [DMAPort1], AL + Mov Byte Ptr [DMAPort2], AL + + Mov AX, DMABUFFERLENGTH/2 + Cmp BX, 4 + JB DetectWSS2 + + ShR AX, 1 + +DetectWSS2: + Mov Word Ptr [DMABufferLength1], AX + Mov Word Ptr [DMABufferLength2], AX + + Mov EAX, 'Jeff' + ClC + Ret + +EndP DetectCard + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +MixModeTable Label Word + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix0ModeMono, Mix0ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + DW Offset Mix6ModeMono, Mix6ModeStereo + +Proc MixSamples ; Given DS:SI = info tables, CX = numchannels + + ; 1. Clean buffer + ; + update variables + ; 2. Update parameters + ; 3. Mix func + ; 4. Return + + Push CX + + Mov CX, BytesToMix + Mov ES, MixSegment + Mov DI, MIXTABLESIZE + Xor EAX, EAX + Mov DX, CX + Add CX, CX + + Mov MixTransferOffset, DI ; } Memory write + + Cmp Stereo, 0 + JE MixSamples1 + + Mov DX, CX + +MixSamples1: + Rep StosD ; } Memory write + Mov MixTransferRemaining, DX ; } + + Pop CX + +MixSamples2: + Test Byte Ptr [SI], 1 + JZ MixSamplesEnd2 + Cmp Byte Ptr [SI+36h], 100 + JE MixSamplesEnd2 + + Push CX + Mov CX, [SI] + + Test CH, 2 + JZ MixSamples3 + And Byte Ptr [SI], Not 1 + + Jmp MixSamplesEnd +; Cmp MixMode, 8 ; Is it volume ramping? +; JB MixSamplesEnd + +MixSamples3: + Test CL, 20h ; New freq? + JZ MixSamples5 + + Mov AX, [SI+10h] + Mov DX, [SI+12h] + Mov BX, MixSpeed + Cmp DX, BX + JAE MixSamplesHandleError + + Div BX + ShL EAX, 16 + Xor AX, AX + Div BX + Mov STEPVALUE, EAX + +MixSamples4: + Test CH, 1 + JZ MixSamples5 + + Mov DWord Ptr [SI+1Ch], 0 ; Current Volume = 0 + ; for volume sliding. +MixSamples5: + Test CX, 8440h ; New volume or panning? + JZ MixSamplesMix + + Xor AX, AX + Test CH, 8 ; Muted? + JNZ MixModeCommon + + Mov BX, MixMode + Add BL, Stereo + Add BX, BX + Jmp [CS:MixModeTable+BX] + +Mix0Mode: ; 16-bit mixing, no interpolation +Mix0ModeMono: ; and 16-bit mixing, interpolation + Mov AL, [SI+20h] + ShR AL, 1 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 30 ; Use left only-mixing for mono + Jmp MixModeCommon + +Mix0ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix0ModeSurround + + Mul Byte Ptr [SI+20h] ; Final volume + Add AX, 64 + ShR AX, 7 + Mov [SI+0Ch], AX ; Store into right volume + + Mov AL, 64 + Sub AL, [SI+37h] + Mul Byte Ptr [SI+20h] + Add AX, 64 + ShR AX, 7 + Mov [SI+0Eh], AX ; Left volume + + Mov CH, AL ; CH = left volume + Mov CL, [SI+0Ch] ; CL = right volume + Mov AX, 0 + + Test CX, CX + JZ MixModeCommon + + Mov AL, 30 ; Left only... + Test CL, CL + JZ MixModeCommon + + Mov AL, 60 + Test CH, CH + JZ MixModeCommon + + Mov AL, 90 + Cmp CL, CH + JZ MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix0ModeSurround: + Mov AL, [SI+20h] + ShR AL, 2 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Mov AX, 0 + JZ MixModeCommon + Mov AL, 150 ; Surround + Jmp MixModeCommon + +Mix6ModeMono: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 8 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + Test AX, AX + JZ MixModeCommon + Mov AX, 30 + Jmp MixModeCommon + +Mix6ModeStereo: + Mov AL, [SI+37h] ; Final pan + Cmp AL, 100 + JE Mix6ModeSurround + + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Ch], AX ; Store into right volume + Mov BX, AX + ShL EAX, 16 + + Mov AL, 64 ; Do left volume + Sub AL, [SI+37h] ; AL = 64-FinalPan + Mul Byte Ptr MixVolume + Mul Word Ptr [SI+4Ah] + ShRD AX, DX, 14 + Mov [SI+0Eh], AX + + Mov ECX, EAX + + ; BX = right volume + ; CX = Left volume + Mov AX, 0 + Test ECX, ECX + JZ MixModeCommon + + Mov AL, 30 + Test BX, BX + JZ MixModeCommon + + Mov AL, 60 + Test CX, CX + JZ MixModeCommon + + Mov AL, 90 + Cmp CX, BX + JE MixModeCommon + + Mov AL, 120 + Jmp MixModeCommon + +Mix6ModeSurround: + Mov AX, [SI+4Ah] + Mul MixVolume + ShRD AX, DX, 9 + Mov [SI+0Ch], AX + Mov [SI+0Eh], AX + JZ MixModeCommon + Mov AX, 150 + Jmp MixModeCommon + +MixModeCommon: ; Requires AX = 30/60/90 etc. depending + ; On mixing mode type. + ; This will add 180 for 16-bit, + ; And sort out loop types. + Mov BL, [SI+0Ah] + Test Byte Ptr [SI+18h], 2 ; 16 bit? + JZ MixModeCommon1 + + Add AX, 180 + +MixModeCommon1: + Cmp BL, 8 + JB MixModeCommon3 ; No loop + JE MixModeCommon2 ; Forwards loop + + Add AX, 10 + +MixModeCommon2: + Add AX, 10 + +MixModeCommon3: + Add AX, Offset MixFunctionTables + Add AX, MixModeOffset + Mov [SI+8], AX ; Offset... + +MixSamplesMix: + Mov BX, [SI+8] ; BX = offset into + Mov EAX, [CS:BX+2] + Mov DWord Ptr PreMixFunction, EAX + Mov EAX, [CS:BX+6] + Mov DWord Ptr MixFunctionSeparateBackwards, EAX + + Mov AX, BytesToMix + Mov MixBlockSize, AX + Mov MixBufferOffset, MIXTABLESIZE + + Mov EAX, CURRENTPOSITION + Mov OLDPOSITION, EAX + + Call Word Ptr [CS:BX] + + And Word Ptr [SI], 0111100010001101b + Jmp MixSamplesEnd + +MixSamplesHandleError: + Mov Word Ptr [SI], 200h + + Test Byte Ptr [SI+3Ah], 80h + JNZ MixSamplesEnd + + Mov BX, [SI+38h] + And Byte Ptr [BX], Not 4 ; Turn off channel + +MixSamplesEnd: + Pop CX + +MixSamplesEnd2: + Add SI, 128 + Dec CX + JNZ MixSamples2 + + Ret + +EndP MixSamples + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WSSIRQHandler + + Push AX + Push BX + Push DS + + Push CS + Pop DS + Assume DS:Driver + + Add TimerAccumulator, TIMERCONST + JC WSSIRQHandler11 + + Mov AL, 20h + Out 20h, AL + Jmp WSSIRQHandler12 + +WSSIRQHandler11: + PushF + Call [OldTimerIRQHandler] + +WSSIRQHandler12: + +DMAPort1 EQU $+1 + In AL, 1 + Mov AH, AL +DMAPort2 EQU $+1 + In AL, 1 + XChg AL, AH + + Cmp MixBufferPos, 0 + JE WSSIRQHandler13 + + Xor BX, BX +DMABufferLength1 EQU $+1 + Cmp AX, 1234h + JB WSSIRQHandler1 + + Pop DS + Pop BX + Pop AX + IRet + +WSSIRQHandler13: + Mov BX, DMABUFFERLENGTH/2 +DMABufferLength2 EQU $+1 + Cmp AX, 1234h + JAE WSSIRQHandler1 + + Pop DS + Pop BX + Pop AX + IRet + +WSSIRQHandler1: + Xor MixBufferPos, 1 + + PushAD + Push ES + + CLD + + + ; OK... time to get next block + ; Check whether stereo thing is on.. + ; + LES DI, [ActualDMAPtr] + Add DI, BX + + Mov BX, DMABUFFERLENGTH/4 ; BX = samples required + Mov BP, 8 ; Skip for mono + Mov CL, 14 ; Shift for mono + + Cmp Stereo, 0 + JE WSSIRQHandlerMono + + Mov BP, 4 ; Stereo skip value. + Dec CL + +WSSIRQHandlerMono: + Call SaveEMSPageFrame + + Cmp MixTransferRemaining, 0 + JNE WSSIRQHandler4 + Assume DS:Nothing + +WSSIRQHandler3: + Push BX + Push CX + Push BP + Push ES + Push DI + + Call Update + Call MixSamples + + Pop DI + Pop ES + Pop BP + Pop CX + Pop BX + +WSSIRQHandler4: + Mov DS, MixSegment + Mov SI, MixTransferOffset + Mov DX, BX ; DX = samples to transfer + Cmp DX, MixTransferRemaining + JBE WSSIRQHandler5 + + Mov DX, MixTransferRemaining + +WSSIRQHandler5: + Push DX + Cmp CS:Filter, 1 + JB WSSIRQHandler6 + JE WSSIRQHFilter + + Cmp CS:Stereo, 0 + JE WSSIRQ3QFilterMono + +WSSIRQ3QFilterStereo: + Push BX + + Mov EBX, FilterValue + Mov EBP, FilterValue2 + ShR DX, 1 + +WSSIRQ3QFilterStereo1: + Mov EAX, EBX + Mov ECX, EBP + Add EAX, [SI] + Add ECX, [SI+4] + SAR EAX, 1 + SAR ECX, 1 + Add EBX, EAX + Add EBP, ECX + SAR EBX, 1 + SAR EBP, 1 + + Mov EAX, EBX + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSS3QFilterStereoClip1 + Cmp EAX, 7FFFh + JG WSS3QFilterStereoClip2 + +WSSIRQ3QFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSS3QFilterStereoClip3 + Cmp EAX, 7FFFh + JG WSS3QFilterStereoClip4 + +WSSIRQ3QFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ WSSIRQ3QFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp WSSMixTransferEnd + +WSSIRQ3QFilterMono: + Push BX + + Mov EBX, FilterValue + +WSSIRQ3QFilterMono1: + Mov EAX, EBX + Add EAX, [SI] + SAR EAX, 1 + Add EBX, EAX + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL WSS3QFilterMonoClip1 + Cmp EAX, 7FFFh + JG WSS3QFilterMonoClip2 + +WSSIRQ3QFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ WSSIRQ3QFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp WSSMixTransferEnd + +WSSIRQHFilter: + Cmp CS:Stereo, 0 + JE WSSIRQHFilterMono + +WSSIRQHFilterStereo: + Push BX + + Mov EBX, FilterValue + Mov EBP, FilterValue2 + ShR DX, 1 + +WSSIRQHFilterStereo1: + Add EBX, [SI] + Add EBP, [SI+4] + + SAR EBX, 1 + SAR EBP, 1 + + Mov EAX, EBX + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSSHFilterStereoClip1 + Cmp EAX, 7FFFh + JG WSSHFilterStereoClip2 + +WSSIRQHFilterStereo2: + StosW + + Mov EAX, EBP + SAR EAX, 13 + + Cmp EAX, -8000h + JL WSSHFilterStereoClip3 + Cmp EAX, 7FFFh + JG WSSHFilterStereoClip4 + +WSSIRQHFilterStereo3: + StosW + + Add SI, 8 + Dec DX + JNZ WSSIRQHFilterStereo1 + + Mov FilterValue, EBX + Mov FilterValue2, EBP + + Pop BX + + Jmp WSSMixTransferEnd + +WSSIRQHFilterMono: + Push BX + + Mov EBX, FilterValue + +WSSIRQHFilterMono1: + Add EBX, [SI] + SAR EBX, 1 + Mov EAX, EBX + SAR EAX, 14 + + Cmp EAX, -8000h + JL WSSHFilterMonoClip1 + Cmp EAX, 7FFFh + JG WSSHFilterMonoClip2 + +WSSIRQHFilterMono2: + StosW + + Add SI, 8 + Dec DX + JNZ WSSIRQHFilterMono1 + + Mov FilterValue, EBX + + Pop BX + + Jmp WSSMixTransferEnd + +WSSIRQHandler6: + Mov EAX, [SI] + SAR EAX, CL + + Cmp EAX, -8000h + JL WSSIRQHandlerClip1 + Cmp EAX, 7FFFh + JG WSSIRQHandlerClip2 + +WSSIRQHandler7: + StosW ; } Memory write + + Add SI, BP + Dec DX + JNZ WSSIRQHandler6 + +WSSMixTransferEnd: + Pop DX + + Sub MixTransferRemaining, DX ; } Memory write + Sub BX, DX + JNZ WSSIRQHandler3 + + Mov MixTransferOffset, SI ; } Memory write + + Call RestoreEMSPageFrame + + Pop ES + PopAD + Pop DS + Pop BX + Pop AX + IRet + +WSSIRQHandlerClip1: + Mov AX, 8000h + Jmp WSSIRQHandler7 + +WSSIRQHandlerClip2: + Mov AX, 7FFFh + Jmp WSSIRQHandler7 + +WSSHFilterMonoClip1: + Mov AX, 8000h + Jmp WSSIRQHFilterMono2 + +WSSHFilterMonoClip2: + Mov AX, 7FFFh + Jmp WSSIRQHFilterMono2 + +WSSHFilterStereoClip1: + Mov AX, 8000h + Jmp WSSIRQHFilterStereo2 + +WSSHFilterStereoClip2: + Mov AX, 7FFFh + Jmp WSSIRQHFilterStereo2 + +WSSHFilterStereoClip3: + Mov AX, 8000h + Jmp WSSIRQHFilterStereo3 + +WSSHFilterStereoClip4: + Mov AX, 7FFFh + Jmp WSSIRQHFilterStereo3 + +WSS3QFilterMonoClip1: + Mov AX, 8000h + Jmp WSSIRQ3QFilterMono2 + +WSS3QFilterMonoClip2: + Mov AX, 7FFFh + Jmp WSSIRQ3QFilterMono2 + +WSS3QFilterStereoClip1: + Mov AX, 8000h + Jmp WSSIRQ3QFilterStereo2 + +WSS3QFilterStereoClip2: + Mov AX, 7FFFh + Jmp WSSIRQ3QFilterStereo2 + +WSS3QFilterStereoClip3: + Mov AX, 8000h + Jmp WSSIRQ3QFilterStereo3 + +WSS3QFilterStereoClip4: + Mov AX, 7FFFh + Jmp WSSIRQ3QFilterStereo3 + +EndP WSSIRQHandler + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc WSSAckIRQ + + Push AX + Push DX + + Mov DX, [CS:BasePort] + Add DX, 6 + In AL, DX + Test AL, 1 + JZ WSSAckIRQ2 + + Xor AL, AL + Out DX, AL + +WSSAckIRQ2: + Mov AL, 20h + Cmp CS:IRQ, 8 + JB WSSAckIRQ1 + + Out 0A0h, AL + +WSSAckIRQ1: + Out 20h, AL + + Pop DX + Pop AX + + IRet + +EndP WSSAckIRQ + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov AL, 34h ; Program IRQ 0. LSB&MSB, Rate gen + Out 43h, AL + + ; bump the interrupt to be called + ; 100 times a second. + Mov AX, TIMERCONST + Out 40h, AL + Mov AL, AH + Out 40h, AL + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset WSSIRQHandler + + ClI + + XChg [ES:20h], EAX ; Hook to timer interrupt + Mov CS:OldTimerIRQHandler, EAX + + StI + + ; Now hook WSS ACK IRQ + Mov DI, IRQ + ShL DI, 2 + Add DI, Offset IRQData + Mov BX, [CS:DI] + + Mov AX, CS + ShL EAX, 16 + Mov AX, Offset WSSACKIRQ + + XChg [ES:BX], EAX + Mov OldWSSIRQHandler, EAX + + Mov AX, IMR + And AX, [DI+2] + + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Pop ES + PopAD + + Ret + +EndP SetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetIRQ + + PushAD + Push ES + + Xor AX, AX + Mov ES, AX + + Mov AL, 34h ; Program IRQ 0. LSB&MSB, Rate gen + Out 43h, AL + + Xor AL, AL + Out 40h, AL ; Interrupt called at normal 18.2 times + Out 40h, AL + + Mov EAX, CS:OldTimerIRQHandler + Mov [ES:20h], EAX + + Mov DI, IRQ + ShL DI, 2 + Mov BX, [IRQData+DI] + + Mov EAX, OldWSSIRQHandler + Mov [ES:BX], EAX + + Pop ES + PopAD + + Ret + +EndP ResetIRQ + Assume DS:Nothing + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StopWSS + + Mov DX, BasePort + Add DX, WSS_BASE + + Mov AL, CODEC_INDEX_INTF + Out DX, AL + Inc DX + In AL, DX + And AL, Not INTF_PEN + Out DX, AL + + Inc DX + In AL, DX + Xor AL, AL + Out DX, AL + + Dec DX + Dec DX + + Mov AL, CODEC_INDEX_PIN + Out DX, AL + Inc DX + Xor AL, AL + Out DX, AL + + Ret + +EndP StopWSS + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc StartWSS + + PushA + Push ES + Push DS + + Push CS + Pop DS + Assume DS:Driver + + ; Setup DMA + Mov BX, DMASegment + Xor AX, AX + Mov DX, DMA + Mov DI, DMABUFFERLENGTH + Call SetDMA + + LES DI, ActualDMAPtr + Xor AX, AX + Mov CX, DMABUFFERLENGTH/2 + Rep StosW + + Mov MixBufferPos, 0 + Mov MixTransferRemaining, 0 + + Mov DX, BasePort + Call PingWSS + + Add DX, WSS_BASE + + Mov AL, CODEC_INDEX_PIN + Out DX, AL + Inc DX + Mov AL, PIN_IEN + Out DX, AL + Dec DX + + Mov AH, WSSMixConst ; Set format/frequency + Cmp Stereo, 0 + JE StartWSS1 + + Or AH, CDF_STEREO + +StartWSS1: + Mov AL, CODEC_MCE or CODEC_INDEX_CDF + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Call WaitCodec + + Mov AL, CODEC_INDEX_CDF + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Call WaitAutoCalibration + + ; Start playback + Mov AL, CODEC_INDEX_LWR_COUNT + Out DX, AL + Inc DX + + Mov AX, 0FFFFh + + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_UPR_COUNT + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_INTF + Out DX, AL + Inc DX + In AL, DX + Or AL, INTF_PEN + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_LDC + Out DX, AL + Inc DX + In AL, DX + And AL, Not LDC_LDM + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_RDC + Out DX, AL + Inc DX + In AL, DX + And AL, Not RDC_RDM + Out DX, AL + Dec DX + + Pop DS + Pop ES + PopA + + Ret + +EndP StartWSS + Assume DS:Nothing + +;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Sets up any memory required for output +; Initiates output +; +; Parameters: AX = Number of Channels +; +; If sucessful, returns: +; Carry flag clear +; DS:SI = pointer to text to display +; AX = parameter 1 in text +; BX = parameter 2 in text +; CX = parameter 3 in text +; DX = parameter 4 in text +; DI = parameter 5 in text +; +; If unsucessful, returns: +; Carry flag set +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc InitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov SI, Offset RelocationTable + +RelocationFix: + LodsW + Test AX, AX + JZ RelocationEnd + Mov BX, AX + Mov [BX], DS + Jmp RelocationFix + + +RelocationEnd: + Call GetEMSPageFrame + Mov EMSPageFrame, AX + + In AL, 0A1h + Mov AH, AL + In AL, 21h + Mov IMR, AX + + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + Mov IdleFunctionList, ECX + Mov GlobalKeyLink2, EDX + + Mov ECX, FillHeaderFunction + Mov EDX, DrawHeaderFunction + Mov FillHeader2, ECX + Mov ScreenHeader2, EDX + + Call GetWSSMixConst + + Mov AX, 2643 + Mul MixSpeed + Add AX, 0FFFFh + AdC DX, 2080 + + Mov BX, (DMABUFFERLENGTH*2)/16 + Add BX, DX + + ; Allocate MixSegment first + Mov AH, 48h + + Int 21h + JNC InitSound1 + +InitSoundNoMemory: + Mov SI, Offset WSSNoMemoryMsg + Ret + +InitSound1: + Mov MixSegment, AX + Add AX, DX + Mov DMASegment, AX + + Call SetIRQ + Call GetTempo + Call SetTempo + + Mov SI, Offset WSSMsg + + Mov AX, BasePort + Mov BX, IRQ + Mov CX, DMA + + Ret + +EndP InitSound + Assume DS:Nothing + +;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Reinitialises sound output +; Initiates sound output +; +; Parameters: AX = number of channels. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReInitSound Far + + PushA + Push DS + Push ES + + Push CS + Pop DS + Assume DS:Driver + + Call ResetIRQ + Call SetIRQ + + Mov SI, Offset ReInitMsg + Mov BX, 40 + Call SetInfoLine + + Mov AL, Stereo + Call SetStereo + + Pop ES + Pop DS + PopA + + Ret + +EndP ReInitSound + Assume DS:Nothing + +;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Stops sound output, releases any memory used by driver +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc UnInitSound Far + + Push CS + Pop DS + Assume DS:Driver + + Mov AX, IMR + Out 21h, AL + Mov AL, AH + Out 0A1h, AL + + Mov AX, MixSegment + Test AX, AX + JZ UnInitSound1 + + Mov ES, AX + Mov AH, 49h ; Release MixSegment + Int 21h + + Call StopWSS + Call ResetIRQ + +UnInitSound1: + Ret + +EndP UnInitSound + Assume DS:Nothing + +;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; This procedure is called as often as possible by IT.EXE +; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song) +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc Poll Far + + Ret + +EndP Poll + +;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: BX = tempo +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetTempo Far + + Push AX + Push BX + Push DX + + Push BX + + Mov AX, MixSpeed + Mov BX, AX + Xor DX, DX + + ShL AX, 1 + RCL DX, 1 ; DX:AX = Mixspeed*2 + + ShR BX, 1 ; BX = Mixspeed/2 + + Add AX, BX + AdC DX, 0 ; DX:AX = Mixspeed*2.5 + + Pop BX ; BX = tempo + Div BX + + Mov BytesToMix, AX + + Pop DX + Pop BX + Pop AX + + Ret + +EndP SetTempo + +;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = MixVolume +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetMixVolume Far + + PushA + Push DS + + Mov BX, AX ; BX = MixVolume + Mov CS:MixVolume, BX + + Mov AX, CS:MixSegment + Test AX, AX + JZ SetMixVolume2 + + Mov DS, AX + + Mov CX, MIXTABLESIZE/2 + Mov SI, MIXTABLESIZE-2; Starting point - working backwards + +SetMixVolume1: + Mov AX, CX + + Dec AX ; AH = volume, AL = wave value. + Xor DX, DX + XChg AH, DL ; DL = Volume, AX = wave value + CBW + + IMul DX ; DX:AX = Volume * Wave Value + ; Ranges -8192->8128 + + IMul BX ; DX:AX = Volume * Wave Value * Mixing Volume + ; Ranges -1048576->1040384 + + Add AX, 64 + AdC DX, 0 + + ShRD AX, DX, 7 + Mov [SI], AX + Sub SI, 2 + + Loop SetMixVolume1 + +SetMixVolume2: + Mov DS, Word Ptr [CS:RecalculateAllVolumes+2] + Call CS: RecalculateAllVolumes + + Pop DS + PopA + + Ret + +EndP SetMixVolume + +;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AL = Stereo on/off, 0 = off. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc RecalculateAllFrequencies + + Call GetChannelTables + +RecalculateAllFrequencies1: + Or Byte Ptr [SI], 32 + + Add SI, 128 + Dec CX + JNZ RecalculateAllFrequencies1 + + Ret + +EndP RecalculateAllFrequencies + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetStereo Far + + Mov CS:Stereo, AL + Cmp CS:MixSegment, 0 + JE SetStereo1 + + Call StopWSS + Call StartWSS + + Call RecalculateAllFrequencies + +SetStereo1: + Ret + +EndP SetStereo + +;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to load +; DS:SI points to sample header +; ES:0 points to first sample +; +; Returns: **Carry set if NO error** +; **Carry clear if error** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc LoadSample Far ; Fix up end of sample bytes + + PushAD + Push DS + Push ES + Push FS + + Mov FS, CS:SongDataArea + Mov BP, AX + Add BP, BP + Mov BP, [FS:64910+BP] + + Xor CX, CX ; From the start of the sample.. + Call GetSampleLocation ; Returns DS:ESI, ECX = length + JC LoadSampleEnd ; Zero flag ON if 16 bit.. + + Xor EAX, EAX + Mov BL, [FS:BP+12h] + + Test BL, 10h ; Loop + JZ LoadSample2 + + Mov ESI, [FS:BP+34h] ; Start of loop + Test BL, 40h ; Pingpong? + JZ LoadSample1 + + Mov ESI, [FS:BP+38h] + Sub ESI, 2 + JNC LoadSample1 + + Xor ESI, ESI + +LoadSample1: + Test BL, 2 + JZ LoadSample4 + + Add ESI, ESI + +LoadSample4: + Call UpdateSampleLocation + Mov AL, [SI] + Inc ESI + Call UpdateSampleLocation + Mov AH, [SI] + +LoadSample2: + Mov ESI, [FS:BP+30h] + Test BL, 2 + JZ LoadSample3 + + Add ESI, ESI + +LoadSample3: + Call UpdateSampleLocation + Mov [SI], AL + Inc ESI + Call UpdateSampleLocation + Mov [SI], AH + +LoadSampleEnd: + Pop FS + Pop ES + Pop DS + PopAD + + StC + Ret + +EndP LoadSample + +;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Parameters: AX = sample to release +; DS:SI points to sample header +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ReleaseSample Far + + Ret + +EndP ReleaseSample + +;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc ResetMemory Far + + Ret + +EndP ResetMemory + +;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Frees all on-board memory +; +; Returns text to show on status line, AX = display parameter +; Carry set if not to show anything. +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetStatus Far + + StC + Ret + +EndP GetStatus + +;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +; Function to have driver interactive part of program +; +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SoundCardScreen Far + + Mov AX, 5 + Mov SI, 1 + Mov CX, CS + Mov DX, Offset WSS16ScreenList + + ClC + Ret + +EndP SoundCardScreen + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc GetVariable Far + + Xor AH, AH + Mov AL, [CS:VolumeTable+DI] + Ret + +EndP GetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +Proc SetVariable Far + + Push DS + Push DX + + Push CS + Pop DS + Assume DS:Driver + + Mov [VolumeTable+DI], AL + + Mov DX, BasePort + Add DX, WSS_BASE + + Mov AL, CODEC_INDEX_LDC + Out DX, AL + Inc DX + Mov AX, 3F3Fh + Sub AX, [Word Ptr VolumeTable] + Out DX, AL + Dec DX + + Mov AL, CODEC_INDEX_RDC + Out DX, AL + Inc DX + Mov AL, AH + Out DX, AL + Dec DX + + Pop DX + Pop DS + Ret + +EndP SetVariable + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +EndDriver: + +;******** Provided Variable Table ************* + +MaxNumberOfChannels DW 0FFFFh ; Maximum number of channels the + ; driver can handle. + +StopAfterPlay DW 0 +DefaultChannels DW 64 + DW 5 Dup (0) + + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + + DW Offset DetectCard + + DW Offset InitSound ; Playing related + DW Offset ReinitSound + DW Offset UninitSound + + DW Offset Poll + + DW Offset SetTempo ; Sound variable related + DW Offset SetMixVolume + DW Offset SetStereo + + DW Offset LoadSample ; Sample related + DW Offset ReleaseSample + DW Offset ResetMemory + DW Offset GetStatus ; Returns string to show on status line + + DW Offset SoundCardScreen ; Sound card 'screen' + + DW Offset GetVariable ; For interface + DW Offset SetVariable + +ProvidedTableEnd: + DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End