home *** CD-ROM | disk | FTP | other *** search
- ;--------------------------------------------------------------------------;
- ; DOS32 32BIT DOS EXTENDER LIBRARY Gravis Ultrasound Routines ;
- ; ;
- ; Written by Adam Seychell ;
- ; ;
- ; ;
- ; Last modified 8rd April 1995 ;
- ; ;
- ;--------------------------------------------------------------------------;
- ; Note The "GF1" is the Ultrasounds programable Synthesizer chip for the
- ; 32 multi-timbral digital 16bit CD quality voices with independed volume
- ; ramping, panning and smapling rate.
- ;
- .386
- .Model flat
- .Code
-
-
- Include GUS.INC ; Define all the publics symbols
-
-
- outp MACRO port,value
- mov al,value
- mov edx,dword ptr port
- out dx,al
- ENDM
-
- FALSE equ 0
- TRUE equ 1
-
-
- ;╒═════════════════════════════════════════════════════════════════════════╕
- ;│ THE GRAVIS UILTRASOUND PORT ADDRESS VARIBLES │
- ;│ │
- ;│ These 12 data vaibles below contian the ultrasounds port addresses. │
- ;│ See the SDK for what each port does. These varibles will be initalized │
- ;│ on the first successful call to the Ultrasound_Reset routine in this │
- ;│ library. │
- ;│ * Do not use these port address varibles until they are initalized as │
- ;│ otherwise they will contian wrong values. │
- ;└─────────────────────────────────────────────────────────────────────────┘
- align 4
- The_Ultrasound_port_Addresses LABEL dword
- GF1_Voice_Select dw 102h ; GF1 Synthesizer
- GF1_REG_Select dw 103h
- GF1_Data_Low dw 104h
- GF1_Data_High dw 105h
- GF1_IRQ_status dw 006h
- GF1_DRAM dw 107h
- GF1_TIMER_Ctrl dw 008h
- GF1_TIMER_Data dw 009h
- Midi_control dw 100h ; MIDI Interface
- Midi_Data dw 101h
- Mix_control dw 000h ; BOARD CONTROL ONLY
- IRQDMA_Ctrl dw 00Bh
- Ultrasound_ports_ends LABEL dword
-
-
-
-
-
-
-
- dma_reg_list db 0,1,0,2,0,3,4,5
- irq_reg_list db 0,0,1,3,0,2,0,4,0,0,0,5,6,0,0,7
- GUS_Base_port dw 0h
- ULTRASND_string db 'ULTRASND='
- GUSdetected_flag db False
-
-
- ;╒═════════════════════════════════════════════════════════════════════════╕
- ;│ GET THE DEFAULT SETTING OF THE GRAVIS UILTRASOUND │
- ;│ │
- ;│ │
- ;│ Looks for the environment varible "ULTRASND" for the default settings │
- ;│ of the Ultrasound. │
- ;│ │
- ;│ IN: nothing │
- ;│ │
- ;│ OUT: Carry is set if couldn't find environment or it has invalid │
- ;│ settings. │
- ;│ │
- ;│ Otherwise the carry flag is cleared and; │
- ;│ BL = GF1 IRQ number ( IRQ is either 0,2,3,5,7,11,12 or 15 ) │
- ;│ BH = MIDI IRQ number │
- ;│ CL = DMA Playback channel ( DMA is either 0,1,3,5,6 or 7 ) │
- ;│ CH = DMA Record channel │
- ;│ DX = Port Address ( 210h,220h,230h,240h,250h or 260h ) │
- ;│ │
- ;└─────────────────────────────────────────────────────────────────────────┘
- GetUltraConfig PROC
-
- local Base_port :WORD
- local dma_control :BYTE
- local irq_control :BYTE
-
- push Eax
- push Edi
- ;
- ; Search for the string "ULTRASND=" in the environment area
- ;
- Mov Ax,0EE02h
- Int 31h ; Returns EDI -> environment
- cld
- Loop_Envir:
- Mov esi,Offset ULTRASND_string
- mov ecx,9
- repe cmpsb
- je Found_string
- xor al,al
- repne scasb
- cmp byte ptr [edi],0
- jne Loop_Envir
- jmp No_ULTRASND
-
-
- Found_string: ; EDI -> first char of string
-
-
- mov ebx,[edi] ; OK, Found the string 'ULTRASND='
- mov eax,ebx ; check for the valid paramters
- and ebx,0ffff00ffh
- cmp ebx,02C300032h ; '2x0,'
- jne No_ULTRASND
- shr eax,8
- call get_digit ; eax = char digit in al
- mov DX,ax ; load port address
- shl edx,4
- add dx,200h
- sub al,1h ; port must be between 210h .. 260h
- cmp al,5h
- ja No_ULTRASND
- add edi,4
-
- ;***** Get playback DMA channel ****
- xor ecx,ecx
- mov al,[edi]
- call get_digit
- cmp dma_reg_list[eax],0
- je No_ULTRASND
- mov CL,AL
- inc edi
- cmp byte ptr [edi],','
- jne No_ULTRASND
-
- ;***** Get record DMA channel ****
- inc edi
- mov al,[edi]
- call get_digit
- cmp dma_reg_list[eax],0
- je No_ULTRASND
- mov CH,AL
- inc edi
- cmp byte ptr [edi],','
- jne No_ULTRASND
-
- ; **** Get IRQ numnber GF1 ****
- xor ebx,ebx
- inc edi
- cmp byte ptr [edi],'1'
- jne J61
- mov BL,10
- inc edi
- J61: mov al,[edi]
- call get_digit
- add al,bl
- cmp al,15
- ja No_ULTRASND
- cmp IRQ_reg_list[eax],0 ; check for valid IRQ number
- je No_ULTRASND
- mov BL,AL
- inc edi
- cmp byte ptr [edi],','
- jne No_ULTRASND
-
- ; **** Get MIDI IRQ numnber *****
-
- inc edi
- cmp byte ptr [edi],'1'
- jne J62
- mov BH,10
- inc edi
- J62: mov al,[edi]
- call get_digit
- add al,bh
- cmp al,15
- ja No_ULTRASND
- cmp IRQ_reg_list[eax],0 ; check for valid IRQ number
- je No_ULTRASND
- mov BH,AL
- ;CHECK FOR STRING ENDING
- inc edi
- cmp byte ptr [edi],','
- je got_it
- cmp byte ptr [edi],' '
- je got_it
- cmp byte ptr [edi],0
- jne No_ULTRASND
-
- got_it:
- clc
- Pop Edi
- Pop Eax
- ret
-
-
- No_ULTRASND:
- stc
- Pop Edi
- Pop Eax
- ret
-
-
- get_digit:
- sub al,'0'
- jc No_digi
- cmp al,9
- ja No_digi
- movzx eax,al
- ret 0
- No_digi:
- add esp,4 ; ignore pushed EIP
- stc
- Pop Edi
- Pop Eax
- ret
-
- GetUltraConfig ENDP
-
-
-
-
-
- comment %
- ╒══════════════════════════════════════════════════════════════════════════╕
- │ COMPLETELY RESET THE GRAVIS ULTRASOUND │
- │ │
- │ │
- │ INPUT: │
- │ BL = GF1 IRQ number ( IRQ must be 0,2,3,5,7,11,12 or 15 ) │
- │ BH = MIDI IRQ number │
- │ CL = DMA Playback channel ( DMA must be 0,1,3,5,6 or 7 ) │
- │ CH = DMA Record channel │
- │ DX = Base port address of the Ultrasound ( must be 2x0h ) │
- │ │
- │ │
- │ OUTPUT: │
- │ The function will fail if an illeagal DMA or IRQ number is selected │
- │ and/or if the card has was not detected at the specified bass address │
- │ │
- │ If function successful the carry is cleared and │
- │ the card is fully reset and all 32 voices are initalised │
- │ EDI = DRAM installed on the ultrasound │
- │ │
- │ Other registers of the GF1 are set as follows │
- │ LINE OUT enabled │
- │ MIC IN disabled │
- │ LINE IN disabled │
- │ │
- │NOTES: │
- │ o This routine will probe the ultrasound on port address DX │
- │ o This function should only need to be used once by your program. │
- │ o Both PICs ( 8259's ) mask registers might be modified. │
- │ o If the IRQ number is ZERO then the Ultrasound is programmed │
- │ with that IRQ disabled. │
- │ o If the DMA channel is ZERO then the Ultrasound is programmed │
- │ with that DMA disabled. │
- │ o EDI will contain the amount of RAM ( in bytes ) installed on the│
- │ Ultrasound however it dos not do a complete RAM test. It will │
- │ always return 0KB, 256KB ,512KB, 768KB or 1024KB. │
- │ │
- └───────────────────────────────────────────────────────────────────────── %
- Ultrasound_Reset PROC
-
- local dma_control :BYTE
- local irq_control :BYTE
- local gf1 :Byte
- local midi :Byte
- local dram :Byte
- local adci :Byte
- local gus_dram_size :Dword
-
-
- pushad
-
- cmp GUSdetected_flag, TRUE ; Don't detect if a GUS has
- je @@skip_detection ; already been detected.
-
-
- ;
- ; check if DX = 2x0h. where x = 1,2,3,4,5,,,F
- ;
- mov eax,edx
- and ax,0F0Fh
- cmp ax,0200h
- jne invalid_setting
- mov al,dl
- and al,0F0h
- jz invalid_setting
-
- call Ultrasound_probe ; See if there's an ultrasound
- jc invalid_setting
-
-
- @@skip_detection:
-
- and bx,0f0fh
- and cx,0707h
- mov GF1,bl ; Save IRQ's
- mov midi,bh
-
- ;**** convert IRQ numbers into register value *****
- movzx edx,bl
- and dl,dl
- jz Zero_irq1
- mov dl,irq_reg_list[edx]
- and dl,dl
- jz invalid_setting
- Zero_irq1: mov irq_control,dl
-
- movzx edx,bh
- and dl,dl
- jz Zero_irq2
- mov dl,irq_reg_list[edx]
- and dl,dl
- jz invalid_setting
- shl dl,3
- Zero_irq2: or irq_control,dl
-
- cmp bh,bl ; Chech if both IRQ
- jne diff_irqs ; are equal then
- and bl,bl ;( Except when zero)
- jz diff_irqs
- and irq_control,0111b ; Clear Channel 2 IRQ
- or irq_control,40h ; and turn on bit 6
- diff_irqs:
-
- ;**** convert DMA number into register value *****
- movzx edx,cl
- and dl,dl
- jz Zero_dma2
- mov dl,dma_reg_list[edx]
- and dl,dl
- jz invalid_setting
- Zero_dma1: mov dma_control,dl
-
- movzx edx,ch
- and dl,dl
- jz Zero_dma2
- mov dl,dma_reg_list[edx]
- and dl,dl
- jz invalid_setting
- shl dl,3
- Zero_dma2: or dma_control,dl
-
- cmp ch,cl ; Chech if both DMAs
- jne diff_dmas ; are equal then
- and cl,cl ;( Except when zero)
- jz diff_irqs
- and dma_control,0111b ; Clear Channel 2 DMA
- or dma_control,40h ; and turn on bit 6.
- diff_dmas:
-
-
-
- cli ; must not be disterbed
-
- ; The code below sets the DMA and IRQ settings of the Ultrasound
- ; It was sort of taken from the file RESET.C of GUS SDK V2.10
-
- mov ecx,200h ; delay a bit
- loop $
-
-
- ;/* Set up for Digital ASIC */
- mov dx,GUS_base_port
- add dx,0fh
- mov al,5
- out dx,al ; Seems to be a undocumented register
-
- outp mix_control,00001011b
- outp IRQDMA_Ctrl,0
-
- mov dx,GUS_base_port
- add dx,0fh
- mov al,0
- out dx,al
-
- ;/* First do DMA control register */
- outp mix_control,00001011b
- mov dx,IRQDMA_Ctrl
- mov al,dma_control
- or al,80h
- out dx,al
-
- ;/* IRQ CONTROL REG */
- outp mix_control,01001011b
- outp IRQDMA_Ctrl,irq_control
-
- ;/* First do DMA control register */
- outp mix_control,00001011b
- outp IRQDMA_Ctrl,dma_control
-
- ;/* IRQ CONTROL REG */
- outp mix_control,01001011b
- outp IRQDMA_Ctrl,irq_control
-
- ;/* IRQ CONTROL, ENABLE IRQ */
- ;/* just to Lock out writes to irq\dma register ... */
- outp GF1_Voice_Select,0
-
- ;/* enable output & irq, disable line & mic input */
- outp mix_control,0001001b
-
- ;/* outp just to Lock out writes to irq\dma register ... */
- outp GF1_Voice_Select,0
-
-
-
- ;
- ; Unmask the IRQ lines for the GF1 and MIDI IRQ settings
- ;
- ; NOTE: the pin labled IRQ 2 on the BUS connects to IRQ 9 of the PIC
- ; controllers. The IRQ 2 on the PIC is used for slave.
- ; The ultrasound SDK ( Software Development Kit ) says that the GUS can use
- ; IRQ 2 this means you must actualy hook IRQ 9.
-
- in al,0A1h
- mov ah,al
- in al,21h
- mov cl,GF1 ; Get GF1 IRQ
- cmp cl , 2 ; gota put right IRQ 2
- jne j3
- mov cl,9
- j3:
- mov ebx,1
- shl ebx,cl
- not ebx
- and eax,ebx
- mov cl,MIDI ; Get MIDI IRQ
- cmp cl , 2 ; gota put right IRQ 2
- jne j4
- mov cl,9
- j4:
- mov ebx,1
- shl ebx,cl
- not ebx
- and eax,ebx
- out 021h,al
- mov al,ah
- out 0A1h,al
- sti
-
-
- ;
- ; Get amount of RAM installed on the sound card (return into EDI)
- ;
- xor edi,edi
- GetSizeloop:
- mov ecx,edi ; Set DRAM I/O address
- call UltraSetDRAM_address
- in al,dx ; see if the DRAM locaion
- mov cl,al ; can store some data
- not al
- out dx,al
- in al,dx
- cmp al,cl
- jz NoDRAM
- add edi,40000h
- cmp edi,100000h ; the GF1 can only hold 1MB
- jb GetSizeloop
-
- NoDRAM: add edi,3ffffh ; align EDI on 256KB
- and edi,NOT 3ffffh
- mov gus_dram_size,edi
-
-
- ;*** Initalise the UltraSound ****
- call Ultrasound_Init
-
- clc
- popad
- mov edi,gus_dram_size
- ret
-
-
- invalid_setting: ; jump here on error
- stc
- popad
- ret
-
- ;=================== Ultrasound reseted ============================
- Ultrasound_Reset ENDP
-
-
- comment %
- ╒══════════════════════════════════════════════════════════════════════════╕
- │ INITALIZE THE ULTRASOUND'S VOICES │
- │ │
- │ │
- │ │
- │ IN: nothing │
- │ │
- │ OUT: All 32 voices have initalized , cleared buffered IRQ's │
- │ enables line out │
- │ Each of the 32 voices are set as follows │
- │ │
- │Frequency = 0 │
- │Voice stoped │
- │Bi-directional looping off │
- │IRQs disabled │
- │Current Volume = 0 │
- │Active Number of Voices = 14 │
- │ │
- │NOTE: │
- │ o This function will only be successful on a successful call │
- │ to the "Ultrasound_Reset" routine │
- └──────────────────────────────────────────────────────────────────────────┘%
- Ultrasound_Init PROC
-
- cmp GUSdetected_flag, TRUE ; do only if gus has
- je GUSok ; been previously detected
- stc
- ret
-
- GUSok:
- pushad
-
- ;/* Pull a reset on the GF1 */
- mov al,04Ch
- mov cl,00000000b
- call Set_GF1_ByteRegister
-
- ;/* Wait a little while ... */
- mov ecx,10
- J56: call GF1_delay
- loop J56
-
- ;/* Release Reset */
- mov al,04Ch
- mov cl,00000001b
- call Set_GF1_ByteRegister
-
- ;/* Wait a little while ... */
- mov ecx,10
- J57: call GF1_delay
- loop J57
-
- ;/* Reset the MIDI port also */
- mov edx,dword ptr midi_control
- mov al,00000011b
- out dx,al
-
- mov ecx,10
- J58: call GF1_delay
- loop J58
-
- xor al,al
- out dx,al
-
- ;/* Clear all interrupts. */
- mov al,41h ;DRAM DMA Control Register
- mov cl,0
- call Set_GF1_ByteRegister
- mov al,045h ;Timer Control Register
- mov cl,00h
- call Set_GF1_ByteRegister
- mov al,049h ;Sampling Control Register
- mov cl,00h
- call Set_GF1_ByteRegister
-
- mov al,0Eh ; set active voices to 32
- mov cl, 31 or 0C0h
- call Set_GF1_ByteRegister
-
-
- ;/* Clear interrupts on voices. */
- ;/* Reading the status ports will clear the irqs. */
- mov edx,dword ptr GF1_IRQ_status ; Read
- in al,dx
- mov al,041h ;DRAM DMA Control Register
- call read_GF1_ByteRegister
- mov al,049h ; Sampling Control Register
- call read_GF1_ByteRegister
- ClrFIFO:mov al,08Fh ;IRQ source Register
- call read_GF1_ByteRegister
- and al,11000000b
- cmp al,11000000b ; keep on reading to clear IRQ's
- jne ClrFIFO
-
-
- mov BL,0
- stop_loop:
- outp GF1_Voice_Select,BL ; select voice to operate with
- mov al,00h ; set Voice control
- mov cl,00000010b ; (Stoped voice )
- call Set_GF1_ByteRegister
- mov al,0Dh ; set Volume Ramp control
- mov cl,00000010b ; ( stoped ramping)
- call Set_GF1_ByteRegister
- mov al,09h ; Current Volume fully off
- xor ecx,ecx
- call Set_GF1_WordRegister
- call GF1_delay ; /* Wait 4.8 micos. or more. */
-
- inc bl
- cmp bl,32
- jb stop_loop
-
-
- mov edx,dword ptr GF1_IRQ_status ; Read
- in al,dx
- mov al,041h ;DRAM DMA Control Register
- call read_GF1_ByteRegister
- mov al,049h ; Sampling Control Register
- call read_GF1_ByteRegister
- Cl2FIFO:mov al,08Fh ;IRQ source Register
- call read_GF1_ByteRegister
- and al,11000000b
- cmp al,11000000b ; keep on reading to clear IRQ's
- jne Cl2FIFO
-
- mov al,0Eh ; set active voices to 14 again
- mov cl, 13 or 0C0h
- call Set_GF1_ByteRegister
-
-
- ;/* Set up GF1 Chip for interrupts & enable DACs. */
- mov al,04Ch
- mov cl,00000111b
- call Set_GF1_ByteRegister
-
- clc
- popad
- ret
- Ultrasound_Init ENDP
-
-
-
-
- ;--------------------- end of ultrasound services ----------------------
-
-
-
- ; Some little procedures that are used by the Ultrasound services
- read_GF1_ByteRegister proc
- mov edx,dword ptr GF1_Reg_Select
- out dx,al
- add dl,2
- in al,dx
- ret
- read_GF1_ByteRegister endp
-
- Set_GF1_ByteRegister proc
- mov edx,dword ptr GF1_Reg_Select
- out dx,al
- add dl,2
- mov al,cl
- out dx,al
- ret
- Set_GF1_ByteRegister endp
-
- Set_GF1_WordRegister proc
- mov edx,dword ptr GF1_Reg_Select
- out dx,al
- inc dl
- mov eax,ecx
- out dx,ax
- ret
- Set_GF1_WordRegister endp
-
-
-
- ;/***************************************************************
- ; * This function is used as a 1.6*3 microsecond (or longer) delay.
- ; * This is needed when trying to change any of the 'self-modifying
- ; * bits in the voice registers.
- ; ***************************************************************/
- GF1_delay PROC
- push edx
- mov ah,7h
- J55: mov dx,GF1_DRAM ; dummy port Read
- in al,dx
- dec ah
- jnz J55
- pop edx
- ret
- GF1_delay ENDP
-
- ;============================================================================
- ;
- ; Probe for an Ultrasound
- ;
- ; Expects DX = Ultrasound base port address
- ;
- ; Returns Carry clear if detected a GUS at this port address
- ; otherwise carry is set.
- ;
- ;============================================================================
- Ultrasound_Probe PROC
- push Eax
- push Edx
- push Ecx
-
- cmp GUSdetected_flag, TRUE ; Don't detect if a GUS has aleady
- je skip_detection ; been detected because some how
- ; I don't think too many pople are
- ; going to be unpluging thier GUS
- ; half way through a game.
-
- mov GUS_Base_Port,DX
- ; Take the Ultrasound out of a reset state
- add dx,103h ; because it's in a reset state at power up.
- mov al,04Ch
- out dx,al
- add dl,2
- mov al,00000111b
- out dx,al
- mov ecx,100h ; delay a bit ????
- loop $
-
-
- xor ecx,ecx ; Set location 0 to 055h
- call UltraSetDRAM_address
- mov al,055h
- out dx,al
-
- inc ecx ; Set location 1 to 0AAh
- call UltraSetDRAM_address
- mov al,0AAh
- out dx,al
-
- xor ecx,ecx ; Read location 0 and
- call UltraSetDRAM_address ; compare it to 055h.
- in al,dx
- cmp al,055h
- jne No_GUS_Found_here
- mov GUSdetected_flag,True ; Set the GUS detected flag
- ;
- ; OK, there is a GUS. Time to initalize the port address varibles.
- ;
- mov ax,GUS_Base_Port
- mov ecx,offset The_Ultrasound_port_Addresses
- PAdrLoop: add [ecx],ax
- add ecx,2
- cmp ecx,offset Ultrasound_ports_ends
- jb PAdrLoop
-
- skip_detection:
- clc
- pop ecx
- pop edx
- pop eax
- ret
-
- No_GUS_Found_here:
- stc
- pop ecx
- pop edx
- pop eax
- ret
-
- Ultrasound_Probe ENDP
-
- ;----------------------------------------------------------
- ; Procedure to set the DRAM I/O address of the Ultrasound
- ;
- ; Expects ECX with address
- ;
- UltraSetDRAM_address PROC
- mov DX,GUS_Base_Port
- add dx,103h
- mov al,043h ; DRAM I/O reg bits 0..15
- out dx,al
- inc dl
- mov eax,ecx
- out dx,ax
- dec dl
- mov al,044h ; DRAM I/O reg bits 16..19
- out dx,al
- add dl,2
- shr eax,16
- out dx,al
- add dl,2 ; set DX to DRAM port
- ret
- UltraSetDRAM_address ENDP
-
-
-
- ;********************* END OF THE ULTRASOUND ROUTINES *********************
- END
-