652 lines
18 KiB
Plaintext
Executable File
652 lines
18 KiB
Plaintext
Executable File
|
||
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
|
||
|
||
;<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>
|
||
|
||
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
|
||
|
||
;<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>
|
||
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
|
||
|
||
|