impulsetracker/SoundDrivers/GUSNRIC.INC

416 lines
12 KiB
Plaintext
Raw Normal View History

;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
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