.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 ³ ÃÄÄÄÂÄÄÄÅÄÄÄÂÄÄÄÅÄÄÄÂÄÄÄÂÄÄÄÂÄÄÄÅÄÄÄÂÄÄÄÅ