home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Large Pack of OldSkool DOS MOD Trackers
/
funk108a.zip
/
FUNK_S.ZIP
/
FUNKLITE.ASM
< prev
next >
Wrap
Assembly Source File
|
1995-07-16
|
214KB
|
6,568 lines
;=1.08a=;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; FunkLite - By Super Real Darwin! ;
; Designed & Coded By Jason Nunn (JsNO) ;
; ;
; The Playback routines.. ;
; ;
; Snail: 32 Rothdale Road, Moil, Darwin, NT, Australia ;
; Email: jsno@amigar.apana.org.au ;
; BBS : ■ Amiga Retreat BBS (3:850/105) ;
; (089)451516 ;
; ;
; ===================================================================== ;
; ;
; Funktracker processes sound exclusively in backround. Unlike many ;
; playback routines that require mixxer calls to be dotted through out ;
; ones code, funktracker processes music totally in backround without any ;
; foreground processing required. ;
; ;
; These is the attachment that contents all code necessary to play a FNK ;
; module. Refer to the EXAMPLE.ASM for a demo of how to use. ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; Global ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Subjective quality Scale (on my Pentium)
;
; SHITHOUSE GOOD EXCELLENT
; │ │ │
;
; SB2.0│*******
; SBPRO│*********************
; GUS│************************************
; SB16│************************************************
; PAS16│**********************************************
;
; ■ PAS16 doesn't sound quite as good as the SB16
SB_CARD = 0
SBPRO_CARD = 1
GUS_VARB_CARD = 2 ;<<---Channel panning can vary according to sample
SB15EM_CARD = 3
SB16_CARD = 4
GUS_FIXB_CARD = 5 ;<<- fixed DAC/669 style left-right-left-right balances
RIPPED_CARD = 6
PAS16_CARD = 7
struc tinit_settings
card_type db ?
PORT_no dd ?
IRQ_no db ?
DMA_no db ?
IRQ_no2 db ?
DMA_no2 db ?
DAC_Samplerate db 4
ends
init_settings tinit_settings <>
struc tDAC_ssetings ; these struc variables control the DMA
DAC_sr dd ? ; a sample rate for each card. The idea
DAC_mix_buffer_size dd ? ; is to maintain a 0.02 of a second
DMA_length dd ? ; tick when processing DAC DMA transfers.
DMA_real_sr dd ? ; both tracker and DAC mixxer run of the same interrupt.
ends
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; Tracker Data ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Structures ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
STOP = 0
PLAY = 1
struc tfunk_sb
sname db 19 dup(?)
start dd ?
length dd ?
volume db ? ; (0 to FF)
balance db ? ; (0 to FF)
pt_and_sop db ?
vv_waveform db ?
rl_and_as db ?
ends
struc tfunk_hr
sig dd ?
info dd ?
LZH_check_size dd ?
LZH_check_sum dd ? ;this field is no longer used for "checksum"
loop_order db ? ; if FFh then no loop
order_list db 256 dup(?)
break_list db 128 dup(?)
funk_sb tfunk_sb 64 dup(<>)
ends
struc tfunk_chan
;─control system─────────────────
channel_kill db PLAY
command db ?
com_val db ?
comspd_count db ? ; crtl rapid speed delay
sample db ? ; thenis serves no purpose
start dd ?
length dd ?
funkctrl db ?
port_type db ?
sample_ofs_parm db ?
vib_waveform db ?
vol_vib_waveform db ?
retrig_spd_count db ?
retrig_count db ?
retrig_limit db ?
arp_speed db ?
balance db ? ; 0 to 15
;─note system────────────────────
note_command db ?
note_com_val db ?
note_comspd_count db ? ; note rapid speed delay
note db ?
ifreq dd ? ; real_freq = FACTOR / invert_freq
ifreq_vibrato dd ? ; used by vibrato, tremola, freqadetc
ifreq_portdest dd ? ; used by porta
rfreq dd ? ; the real frequency
rfreq_adjust dd ?
rfreq_portdest dd ?
vib_ptr db ?
note_beat_count db ? ; used by arpeggio and retrig, fanin, fanout
;─volume system──────────────────
volume_command db ?
volume_com_val db ?
volume_comspd_count db ? ; volume rapid speed delay
volume db ?
volume_vibrato db ?
volume_portdest db ?
rvolume db ?
vol_vib_ptr db ?
volume_beat_count db ? ; used by reverb, crest, though
;─card dependant─────────────────
CARD_sample_ptr dd ?
CARD_freq dd ?
CARD_freq_attract dd ?
CARD_volume dd ?
ends
struc tfunk_info
trek_status db ?
sequence_ofs db ?
pattern_ofs db ?
sequence_ofs_old db ? ;for display purposes
pattern_ofs2_old db ?
tempo db ?
tempo_count db ?
no_of_patterns db ?
no_of_sequences db ?
master_volume db ?
sample_ptrs dd 64 dup(?)
sample_block_size dd ?
funk_pd_size db 80h
sample_memory_lim dd 00100000h
ends
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; var ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
note_table:
dd 13696,12928,12192,11520,10848,10240, 9664, 9120, 8608, 8128, 7680
dd 7248, 6848, 6464, 6096, 5760, 5424, 5120, 4832, 4560, 4304, 4064
dd 3840, 3624, 3424, 3232, 3048, 2880, 2712, 2560, 2416, 2280, 2152
dd 2032, 1920, 1808, 1712, 1616, 1520, 1440, 1360, 1280, 1208, 1144
dd 1080, 1016, 960, 904, 856, 808, 760, 720, 680, 640, 600
dd 568, 536, 504, 480, 448, 0, 0, 0, 0
com_ifreq_inc:
db 001,004,006,010,012,016,020,024
db 031,047,063,083,107,139,187,251
com_rfreq_inc:
dd 00016,00032,00048,00064,00096,00128,00160,00192
dd 00244,00255,00383,00511,00639,00767,00895,01024
com_volume_inc:
db 001,002,003,004,005,006,007,008
db 010,012,016,020,024,032,048,064
com_sine_table:
db -6, -19, -31, -43, -55, -66, -76, -86
db -95,-103,-110,-116,-120,-124,-127,-128
db -128,-127,-124,-121,-116,-110,-103, -95
db -86, -77, -66, -55, -44, -32, -19, -7
db 6, 18, 30, 42, 54, 65, 76, 85
db 94, 102, 109, 115, 120, 124, 126, 127
db 127, 126, 124, 121, 116, 110, 104, 96
db 87, 77, 67, 56, 44, 32, 20, 8
com_triangle_table:
db -4, -12, -20, -28, -36, -44, -52, -60
db -68, -76, -84, -92,-100,-108,-116,-124
db -124,-116,-108,-100, -92, -84, -76, -68
db -60, -52, -44, -36, -28, -20, -12, -4
db 4, 12, 20, 28, 36, 44, 52, 60
db 68, 76, 84, 92, 100, 108, 116, 124
db 123, 115, 107, 99, 91, 83, 75, 67
db 59, 51, 43, 35, 27, 19, 11, 3
com_square_table:
db -064,-128,-128,-127,-127,-128,-128,-127
db -127,-128,-128,-127,-127,-128,-128,-127
db -127,-128,-128,-127,-127,-128,-128,-127
db -127,-128,-128,-127,-127,-128,-128,-064
db 095, 127, 127, 126, 126, 127, 127, 126
db 126, 127, 127, 126, 126, 127, 127, 126
db 126, 127, 127, 126, 126, 127, 127, 126
db 126, 127, 127, 126, 126, 127, 127, 095
com_sawtooth_table:
db -1, -5, -9, -13, -17, -21, -25, -29
db -33, -37, -41, -45, -49, -53, -57, -61
db -65, -69, -73, -77, -81, -85, -89, -93
db -97,-101,-105,-109,-113,-117,-121,-125
db 127, 123, 119, 115, 111, 107, 103, 99
db 95, 91, 87, 83, 79, 75, 71, 67
db 63, 59, 55, 51, 47, 43, 39, 35
db 31, 27, 23, 19, 15, 11, 7, 3
com_random_table:
db 168, 167, 167, 165, 201, 201, 202, 201
db 244, 244, 244, 244, 85, 82, 85, 85
db 44, 44, 44, 44, 114, 114, 114, 114
db 77, 77, 73, 77, 116, 116, 116, 116
db 87, 87, 87, 87, 31, 31, 31, 31
db 198, 198, 198, 198, 105, 104, 105, 105
db 103, 105, 103, 103, 166, 166, 165, 166
db 171, 172, 171, 171, 217, 217, 217, 217
funk_info tfunk_info <>
funk_chan1 tfunk_chan <>
funk_chan2 tfunk_chan <>
funk_chan3 tfunk_chan <>
funk_chan4 tfunk_chan <>
funk_chan5 tfunk_chan <>
funk_chan6 tfunk_chan <>
funk_chan7 tfunk_chan <>
funk_chan8 tfunk_chan <>
CARD_freq_convert dd ?
CARD_volume_convert dd ?
funk_hr_ptr dd ?
funk_sd_ptr dd ?
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; GET IRQ vector ;
; expects BL = IRQ (0..15) ;
; returns CX = selector ;
; EDX = offset ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc getirqvector
push eax ebx
and bl,0fh
cmp bl,8
jb @@J2
add bl,60h
@@J2: add bl,8h
mov ax,204h
int 31h
pop ebx eax
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;SET IRQ vector ;
; expects BL = IRQ (0..15) ;
; CX = selector ;
; EDX = offset ;
; returns Nothing ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc setirqvector
push eax ebx
and bl,0fh
cmp bl,8
jb @@J1
add bl,60h
@@J1: add bl,8h
mov ax,205h
int 31h
pop ebx eax
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; Tracker Code ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; ebx = ifreq, returns = eax ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc ifreq_to_rfreq_vib
add ebx,[dword edi+tfunk_chan.ifreq_vibrato]
js @@zero
jz @@zero
jmp @@set_r
@@zero:
mov ebx,1
@@set_r:
proc ifreq_to_rfreq
xor edx,edx
mov eax,1b4f4d0h
div ebx
add eax,[dword edi+tfunk_chan.rfreq_adjust] ; add 669 freq adjustment
ret
endp
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc vol_to_realvol
mov bl,[byte edi+tfunk_chan.volume]
mov [byte edi+tfunk_chan.rvolume],bl
ret
endp
proc vol_to_realvol_vib
movzx ebx,[byte edi+tfunk_chan.volume]
add ebx,1000
movzx eax,[byte edi+tfunk_chan.volume_vibrato]
or al,al
js @@sub
add ebx,eax
cmp ebx,1000+0ffh
ja @@adjust_add
jmp @@done
@@adjust_add:
mov ebx,1000+0ffh
jmp @@done
@@sub:
neg al
sub ebx,eax
cmp ebx,1000
jb @@adjust_sub
jmp @@done
@@adjust_sub:
mov ebx,1000
@@done:
sub ebx,1000
mov [byte edi+tfunk_chan.rvolume],bl
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; bl = note, returns bx = ifreq ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
macro @note_2_ifreq
and ebx,111111b
lea ebx,[ebx*4]
mov ebx,[dword ebx+note_table]
endm
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; misc. vibrato function used by ;
; frequency and volume functions ;
; ;
; al = waveform ;
; ah = amplitude ;
; cl = speed ;
; ebx = ptr to vibrato table ;
; returns al = value, ebx = ptr ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc com_vib_func
inc ah
cmp al,1
je @@vib_triangle
cmp al,2
je @@vib_square
cmp al,3
je @@vib_sawtooth
cmp al,4
je @@vib_random
@@vib_sine:
mov al,[byte ebx+com_sine_table]
jmp @@get_func_value
@@vib_triangle:
mov al,[byte ebx+com_triangle_table]
jmp @@get_func_value
@@vib_square:
mov al,[byte ebx+com_square_table]
jmp @@get_func_value
@@vib_sawtooth:
mov al,[byte ebx+com_sawtooth_table]
jmp @@get_func_value
@@vib_random:
mov al,[byte ebx+com_random_table]
@@get_func_value:
imul ah
shr eax,4
not cl
and cl,1111b
add bl,cl
inc bl
and bl,111111b
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; for NOTE 3D: reload samples ;
; attributes ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc reload_sample_attr
movzx eax,[word esi] ;extract sample no
xchg al,ah
shr eax,4
and eax,03fh
mov [byte edi+tfunk_chan.sample],al
shl eax,5
add eax,[funk_hr_ptr]
add eax,offset (tfunk_hr).funk_sb
proc reload_sample2
mov bl,[byte eax+tfunk_sb.balance] ; get balance
mov [byte edi+tfunk_chan.balance],bl
mov bl,[byte eax+tfunk_sb.pt_and_sop] ; get both port type and sample ofs parm
mov dl,bl
shr bl,4
and dl,1111b
mov [byte edi+tfunk_chan.port_type],bl
mov [byte edi+tfunk_chan.sample_ofs_parm],dl
mov bl,[byte eax+tfunk_sb.vv_waveform] ; get both vibrato wf & tremola wf
mov dl,bl
shr bl,4
and dl,1111b
mov [byte edi+tfunk_chan.vib_waveform],bl
mov [byte edi+tfunk_chan.vol_vib_waveform],dl
mov bl,[byte eax+tfunk_sb.rl_and_as] ; get both retrig speed & arp speed
mov dl,bl
shr bl,4
and dl,1111b
mov [byte edi+tfunk_chan.retrig_limit],bl
mov [byte edi+tfunk_chan.arp_speed],dl
mov dl,[byte eax+tfunk_sb.volume]
ret
endp
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc decode_sample
movzx eax,[word esi] ;extract sample no
xchg al,ah
shr eax,4
and eax,03fh
mov [byte edi+tfunk_chan.sample],al
proc do_retrig_sample
movzx eax,al
push eax
shl eax,5
add eax,[funk_hr_ptr]
add eax,offset (tfunk_hr).funk_sb
mov [byte edi+tfunk_chan.funkctrl],10b ; set funkctrl
mov ebx,[dword eax+tfunk_sb.start]
cmp ebx,0ffffffffh
je @@dont_loop
mov [byte edi+tfunk_chan.funkctrl],11b ; set funkctrl
@@dont_loop:
mov [dword edi+tfunk_chan.start],ebx
mov ebx,[dword eax+tfunk_sb.length]
mov [dword edi+tfunk_chan.length],ebx
call reload_sample2
pop eax
lea eax,[eax*4]
mov eax,[dword eax+funk_info.sample_ptrs]
add [dword edi+tfunk_chan.start],eax
add [dword edi+tfunk_chan.length],eax
mov [dword edi+tfunk_chan.CARD_sample_ptr],eax
ret
endp
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc do_full_note
mov [byte edi+tfunk_chan.note],bl
mov bl,[byte edi+tfunk_chan.note]
mov [byte edi+tfunk_chan.volume],dl
@note_2_ifreq
mov [dword edi+tfunk_chan.ifreq],ebx
call ifreq_to_rfreq
mov [dword edi+tfunk_chan.rfreq],eax
call vol_to_realvol
call [dword CARD_freq_convert]
call [dword CARD_volume_convert]
ret
endp
proc load_attr_active
mov [byte edi+tfunk_chan.volume],dl
call vol_to_realvol
call [dword CARD_volume_convert]
ret
endp
proc normal_decode_system
mov bl,[byte esi] ;extract note value
shr bl,2
cmp bl,3dh ; of ReLOad samples then ...
je @@ReLOad_samples
push ebx
call decode_sample
pop ebx
cmp bl,3eh ; of SAMPLE ONLY slot
je @@no_note_change ; then dont change note
mov [byte edi+tfunk_chan.note_command],0fh
mov [byte edi+tfunk_chan.volume_command],0fh
call do_full_note
@@no_note_change:
ret
@@ReLOad_samples:
call reload_sample_attr
call load_attr_active
ret
endp
proc normal_decode_note
mov bl,[byte esi] ;extract note value
shr bl,2
cmp bl,3dh ; of ReLOad samples then ...
je @@ReLOad_samples
push ebx
call decode_sample
pop ebx
cmp bl,3eh ; of SAMPLE ONLY slot
je @@no_note_change ; then dont change note
mov [byte edi+tfunk_chan.volume_command],0fh
call do_full_note
@@no_note_change:
ret
@@ReLOad_samples:
call reload_sample_attr
call load_attr_active
ret
endp
proc normal_decode_volume
mov bl,[byte esi] ;extract note value
shr bl,2
cmp bl,3dh ; of ReLOad samples then ...
je @@ReLOad_samples
push ebx
call decode_sample
pop ebx
cmp bl,3eh ; of SAMPLE ONLY slot
je @@no_note_change ; then dont change note
mov [byte edi+tfunk_chan.note_command],0fh
call do_full_note
@@no_note_change:
ret
@@ReLOad_samples:
call reload_sample_attr
call load_attr_active
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc comc_decode
mov bl,[byte esi] ;extract note value
shr bl,2
cmp bl,3dh ; of ReLOad samples then ...
je @@ReLOad_samples
push ebx
call decode_sample
pop ebx
cmp bl,3eh ; of SAMPLE ONLY slot
je @@cc_no_note_change ; then dont change note
mov [byte edi+tfunk_chan.volume_command],0fh
mov [byte edi+tfunk_chan.volume],dl
mov [byte edi+tfunk_chan.note],bl
@note_2_ifreq
mov [dword edi+tfunk_chan.ifreq_portdest],ebx
call ifreq_to_rfreq
mov [dword edi+tfunk_chan.rfreq_portdest],eax
call vol_to_realvol
call [dword CARD_freq_convert]
call [dword CARD_volume_convert]
@@cc_no_note_change:
ret
@@ReLOad_samples:
call reload_sample_attr
call load_attr_active
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc comi_decode
mov bl,[byte esi] ;extract note value
shr bl,2
cmp bl,3dh ; of ReLOad samples then ...
je @@ReLOad_samples
push ebx
call decode_sample
pop ebx
cmp bl,3eh ; of SAMPLE ONLY slot
je @@no_note_change ; then dont change note
mov [byte edi+tfunk_chan.note_command],0fh
mov [byte edi+tfunk_chan.volume_portdest],dl
mov [byte edi+tfunk_chan.note],bl
@note_2_ifreq
mov [dword edi+tfunk_chan.ifreq],ebx
call ifreq_to_rfreq
mov [dword edi+tfunk_chan.rfreq],eax
call vol_to_realvol
call [dword CARD_freq_convert]
call [dword CARD_volume_convert]
ret
@@no_note_change:
mov [byte edi+tfunk_chan.note_command],0fh
mov [byte edi+tfunk_chan.volume_portdest],dl
call vol_to_realvol
call [dword CARD_freq_convert]
call [dword CARD_volume_convert]
ret
@@ReLOad_samples:
call reload_sample_attr
jmp @@no_note_change
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;0Com A: port up ;
; ;
; com_val : 0000 0000 ;
; \rate/ ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc com_port_up_log
mov bl,[byte edi+tfunk_chan.note_com_val]
and ebx,1111b
movzx eax,[byte ebx+com_ifreq_inc]
sub [dword edi+tfunk_chan.ifreq],eax
cmp [dword edi+tfunk_chan.ifreq],300
ja @@done
mov [byte edi+tfunk_chan.note_command],0fh
mov [dword edi+tfunk_chan.ifreq],300
@@done:
mov ebx,[dword edi+tfunk_chan.ifreq]
call ifreq_to_rfreq
mov [dword edi+tfunk_chan.rfreq],eax
call [dword CARD_freq_convert]
ret
endp
proc com_port_up_lin
mov bl,[byte edi+tfunk_chan.note_com_val]
and ebx,1111b
lea ebx,[ebx*4]
mov eax,[dword ebx+com_rfreq_inc]
add [dword edi+tfunk_chan.rfreq],eax
cmp [dword edi+tfunk_chan.rfreq],174deh
jb @@done
mov [byte edi+tfunk_chan.note_command],0fh
mov [dword edi+tfunk_chan.rfreq],174deh
@@done:
call [dword CARD_freq_convert]
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;1Com B: port down ;
; ;
; com_val : 0000 0000 ;
; \rate/ ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc com_port_dn_log
mov bl,[byte edi+tfunk_chan.note_com_val]
and ebx,1111b
movzx eax,[byte ebx+com_ifreq_inc]
add [dword edi+tfunk_chan.ifreq],eax
cmp [dword edi+tfunk_chan.ifreq],20000
jb @@done
mov [byte edi+tfunk_chan.note_command],0fh
mov [dword edi+tfunk_chan.ifreq],20000
@@done:
mov ebx,[dword edi+tfunk_chan.ifreq]
call ifreq_to_rfreq
mov [dword edi+tfunk_chan.rfreq],eax
call [dword CARD_freq_convert]
ret
endp
proc com_port_dn_lin
mov bl,[byte edi+tfunk_chan.note_com_val]
and ebx,1111b
lea ebx,[ebx*4]
mov eax,[dword ebx+com_rfreq_inc]
sub [dword edi+tfunk_chan.rfreq],eax
cmp [dword edi+tfunk_chan.rfreq],1431
ja @@done
mov [byte edi+tfunk_chan.note_command],0fh
mov [dword edi+tfunk_chan.rfreq],1431
@@done:
call [dword CARD_freq_convert]
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;2Com C: port to note ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc com_porta_log
mov eax,[dword edi+tfunk_chan.ifreq_portdest]
cmp [dword edi+tfunk_chan.ifreq],eax
jne @@not_same
mov [byte edi+tfunk_chan.note_command],0fh
ret
@@not_same:
ja @@do_portup
call com_port_dn_log
mov eax,[dword edi+tfunk_chan.ifreq_portdest]
cmp [dword edi+tfunk_chan.ifreq],eax
jb @@done
mov [byte edi+tfunk_chan.note_command],0fh
mov [dword edi+tfunk_chan.ifreq],eax
jmp @@done
@@do_portup:
call com_port_up_log
mov eax,[dword edi+tfunk_chan.ifreq_portdest]
cmp [dword edi+tfunk_chan.ifreq],eax
ja @@done
mov [byte edi+tfunk_chan.note_command],0fh
mov [dword edi+tfunk_chan.ifreq],eax
@@done:
mov ebx,[dword edi+tfunk_chan.ifreq]
call ifreq_to_rfreq
mov [dword edi+tfunk_chan.rfreq],eax
call [dword CARD_freq_convert]
ret
endp
proc com_porta_lin
mov eax,[dword edi+tfunk_chan.rfreq_portdest]
cmp [dword edi+tfunk_chan.rfreq],eax
jne @@not_same
mov [byte edi+tfunk_chan.note_command],0fh
ret
@@not_same:
jb @@do_portup
call com_port_dn_lin
mov eax,[dword edi+tfunk_chan.rfreq_portdest]
cmp [dword edi+tfunk_chan.rfreq],eax
ja @@done
mov [byte edi+tfunk_chan.note_command],0fh
mov [dword edi+tfunk_chan.rfreq],eax
jmp @@done
@@do_portup:
call com_port_up_lin
mov eax,[dword edi+tfunk_chan.rfreq_portdest]
cmp [dword edi+tfunk_chan.rfreq],eax
jb @@done
mov [byte edi+tfunk_chan.note_command],0fh
mov [dword edi+tfunk_chan.rfreq],eax
@@done:
call [dword CARD_freq_convert]
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc note_system_rapid_p1
mov eax,[dword edi+tfunk_chan.note_command]
cmp al,02h
jbe @@do_rp1
ret
@@do_rp1:
shr ah,4
cmp [byte edi+tfunk_chan.note_comspd_count],ah
jae @@speed_match
inc [byte edi+tfunk_chan.note_comspd_count]
ret
@@speed_match:
mov [byte edi+tfunk_chan.note_comspd_count],0
cmp [byte edi+tfunk_chan.port_type],1
je @@line_porta
or al,al
je @@command_a_i
cmp al,01h
je @@command_b_i
cmp al,02h
je @@command_c_i
ret
@@line_porta:
or al,al
je @@command_a_r
cmp al,01h
je @@command_b_r
cmp al,02h
je @@command_c_r
ret
@@command_a_i:
call com_port_up_log
ret
@@command_a_r:
call com_port_up_lin
ret
@@command_b_i:
call com_port_dn_log
ret
@@command_b_r:
call com_port_dn_lin
ret
@@command_c_i:
call com_porta_log
ret
@@command_c_r:
call com_porta_lin
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;3Com D: vibrato ;
; ;
; com_val : 0000 0000 ;
; \speed/ \amplitude/ ;
; ;
;vib_waveform = 0 : sine ;
; 1 : triangle ;
; 2 : square ;
; 3 : sawtooth ;
; 4 : random ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc com_vibrato
mov ah,[byte edi+tfunk_chan.note_com_val]
mov cl,ah
and ah,00001111b
shr cl,4
proc com_vibrato_minor
movzx ebx,[byte edi+tfunk_chan.vib_ptr]
mov al,[byte edi+tfunk_chan.vib_waveform]
call com_vib_func
mov [byte edi+tfunk_chan.vib_ptr],bl
movsx eax,al
shl eax,1
mov [dword edi+tfunk_chan.ifreq_vibrato],eax
mov ebx,[dword edi+tfunk_chan.ifreq]
call ifreq_to_rfreq_vib
mov [dword edi+tfunk_chan.rfreq],eax
call [dword CARD_freq_convert]
ret
endp
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;4Com E: vibrato Fanin ;
; ;
; com_val : 0000 0000 ;
; \speed/ \fanin value/ ;
; ;
;vib_waveform = 0 : sine ;
; 1 : triangle ;
; 2 : square ;
; 3 : sawtooth ;
; 4 : random ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc com_vib_fanin
mov ah,[byte edi+tfunk_chan.note_com_val]
mov cl,ah
and ah,00001111b
and cl,11110000b
shr cl,2
cmp [byte edi+tfunk_chan.note_beat_count],0fh
jae @@do_vibrato
cmp [byte edi+tfunk_chan.note_comspd_count],cl
jae @@inc_fan
inc [byte edi+tfunk_chan.note_comspd_count]
jmp @@do_vibrato
@@inc_fan:
mov [byte edi+tfunk_chan.note_comspd_count],0
inc [byte edi+tfunk_chan.note_beat_count]
@@do_vibrato:
mov cl,[byte edi+tfunk_chan.note_beat_count]
call com_vibrato_minor
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;5Com F: vibrato Fanout ;
; ;
; com_val : 0000 0000 ;
; \speed/ \fanin value/ ;
; ;
;vib_waveform = 0 : sine ;
; 1 : triangle ;
; 2 : square ;
; 3 : sawtooth ;
; 4 : random ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc com_vib_fanout
mov ah,[byte edi+tfunk_chan.note_com_val]
mov cl,ah
and ah,00001111b
and cl,11110000b
shr cl,2
cmp [byte edi+tfunk_chan.note_beat_count],0
je @@do_vibrato
cmp [byte edi+tfunk_chan.note_comspd_count],cl
jae @@dec_fan
inc [byte edi+tfunk_chan.note_comspd_count]
jmp @@do_vibrato
@@dec_fan:
mov [byte edi+tfunk_chan.note_comspd_count],0
dec [byte edi+tfunk_chan.note_beat_count]
@@do_vibrato:
mov cl,[byte edi+tfunk_chan.note_beat_count]
call com_vibrato_minor
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;6Com G: volume sld up ;
; ;
; com_val : 0000 0000 ;
; \rate/ ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc com_vol_up
mov bl,[byte edi+tfunk_chan.volume_com_val]
and ebx,1111b
mov al,[byte ebx+com_volume_inc]
mov ah,[byte edi+tfunk_chan.volume]
add ah,al
jnc @@adjust
mov [byte edi+tfunk_chan.volume_command],0fh
mov [byte edi+tfunk_chan.volume],255
jmp @@done
@@adjust:
mov [byte edi+tfunk_chan.volume],ah
@@done:
call vol_to_realvol
call [dword CARD_volume_convert]
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;7Com H: volume slide down ;
; ;
; com_val : 0000 0000 ;
; \rate/ ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc com_vol_dn
mov bl,[byte edi+tfunk_chan.volume_com_val]
and ebx,1111b
mov al,[byte ebx+com_volume_inc]
mov ah,[byte edi+tfunk_chan.volume]
sub ah,al
jnc @@adjust
mov [byte edi+tfunk_chan.volume_command],0fh
mov [byte edi+tfunk_chan.volume],0
jmp @@done
@@adjust:
mov [byte edi+tfunk_chan.volume],ah
@@done:
call vol_to_realvol
call [dword CARD_volume_convert]
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;8Com I: volume porta (Rapid ctrl) ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc com_vol_porta
mov al,[byte edi+tfunk_chan.volume_portdest]
cmp [byte edi+tfunk_chan.volume],al
jne @@not_same
mov [byte edi+tfunk_chan.volume_command],0fh
jmp @@done
@@not_same:
jb @@do_portup
call com_vol_dn
mov al,[byte edi+tfunk_chan.volume_portdest]
cmp [byte edi+tfunk_chan.volume],al
ja @@done
mov [byte edi+tfunk_chan.volume_command],0fh
mov [byte edi+tfunk_chan.volume],al
jmp @@done
@@do_portup:
call com_vol_up
mov al,[byte edi+tfunk_chan.volume_portdest]
cmp [byte edi+tfunk_chan.volume],al
jb @@done
mov [byte edi+tfunk_chan.volume_command],0fh
mov [byte edi+tfunk_chan.volume],al
@@done:
call vol_to_realvol
call [dword CARD_volume_convert]
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc volume_system_rapid_p1
mov eax,[dword edi+tfunk_chan.volume_command]
cmp al,06h
jae @@do_rp1
ret
@@do_rp1:
cmp al,08h
jbe @@do_rp2
ret
@@do_rp2:
shr ah,4
cmp [byte edi+tfunk_chan.volume_comspd_count],ah
jae @@speed_match
inc [byte edi+tfunk_chan.volume_comspd_count]
ret
@@speed_match:
mov [byte edi+tfunk_chan.volume_comspd_count],0
cmp al,06h
je @@command_g
cmp al,07h
je @@command_h
cmp al,08h
je @@command_i
ret
@@command_g:
call com_vol_up
ret
@@command_h:
call com_vol_dn
ret
@@command_i:
call com_vol_porta
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;9Com J: Volume Reverb ;
; ;
; A simulated echo effect ;
; ;
; com_val : 0000 0000 ;
; ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc com_reverb
mov cl,[byte edi+tfunk_chan.volume_com_val]
mov ch,cl
mov dl,cl
and ch,00001111b
and cl,11110000b
shr cl,2
cmp [byte edi+tfunk_chan.volume_comspd_count],cl
jae @@echo
inc [byte edi+tfunk_chan.volume_comspd_count]
@@do_slide:
cmp [byte edi+tfunk_chan.volume],0
je @@done
movzx ecx,ch
mov al,[byte ecx+com_volume_inc]
mov ah,[byte edi+tfunk_chan.volume]
sub ah,al
jnc @@adjust
mov [byte edi+tfunk_chan.volume],0
jmp @@done
@@adjust:
mov [byte edi+tfunk_chan.volume],ah
@@done:
call vol_to_realvol
call [dword CARD_volume_convert]
ret
@@echo:
mov [byte edi+tfunk_chan.volume_comspd_count],0
neg dl
shr dl,4
sub [byte edi+tfunk_chan.volume_beat_count],dl
jc @@end
mov al,[byte edi+tfunk_chan.volume_beat_count]
mov [byte edi+tfunk_chan.volume],al
jmp @@done
@@end:
mov [byte edi+tfunk_chan.volume_command],0fh
mov [byte edi+tfunk_chan.volume],0
call vol_to_realvol
call [dword CARD_volume_convert]
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;ACom K: tremola ;
; ;
; com_val : 0000 0000 ;
; \rate/ ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc com_tremola
mov ah,[byte edi+tfunk_chan.volume_com_val]
mov cl,ah
and ah,00001111b
shr cl,4
movzx ebx,[byte edi+tfunk_chan.vol_vib_ptr]
mov al,[byte edi+tfunk_chan.vol_vib_waveform]
call com_vib_func
mov [byte edi+tfunk_chan.vol_vib_ptr],bl
mov [byte edi+tfunk_chan.volume_vibrato],al
call vol_to_realvol_vib
call [dword CARD_volume_convert]
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;BCom L: arpeggio ;
; ;
; com_val : 0000 0000 ;
; \N1/ \N2/ ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc com_arpeggio
mov al,[byte edi+tfunk_chan.note_com_val]
mov bh,[byte edi+tfunk_chan.arp_speed]
cmp [byte edi+tfunk_chan.note_comspd_count],bh
jae @@speed_match
inc [byte edi+tfunk_chan.note_comspd_count]
ret
@@speed_match:
mov [byte edi+tfunk_chan.note_comspd_count],0
mov bl,[byte edi+tfunk_chan.note]
cmp [byte edi+tfunk_chan.note_beat_count],1 ; arp_type 1
je @@arp1_t1
cmp [byte edi+tfunk_chan.note_beat_count],2
je @@arp1_t2
jmp @@done
@@arp1_t1:
shr al,4
jmp @@arp_it
@@arp1_t2:
and al,1111b
@@arp_it:
add bl,al
cmp bl,59
jbe @@done
mov bl,[byte edi+tfunk_chan.note]
@@done:
@note_2_ifreq
mov [dword edi+tfunk_chan.ifreq],ebx
call ifreq_to_rfreq
mov [dword edi+tfunk_chan.rfreq],eax
call [dword CARD_freq_convert]
cmp [byte edi+tfunk_chan.note_beat_count],2
je @@clr_b
inc [byte edi+tfunk_chan.note_beat_count]
ret
@@clr_b:
mov [byte edi+tfunk_chan.note_beat_count],0
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;CCom M: sample offset ;
; ;
; This is a all present sample ;
; offset that is effective all the ;
; time for a given channel ;
; ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc com_sample_offset
movzx eax,[byte edi+tfunk_chan.com_val]
mov cl,[byte edi+tfunk_chan.sample_ofs_parm]
shl eax,cl
add [dword edi+tfunk_chan.CARD_sample_ptr],eax
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;DCom N: volume ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc com_volume
mov al,[byte edi+tfunk_chan.volume_com_val]
mov [byte edi+tfunk_chan.volume],al
call vol_to_realvol
call [dword CARD_volume_convert]
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;ECom O0: misc control ;
; ;
;value control set ;
;------------------ ;
;0 vibrato sine ;
;1 vibrato triangle ;
;2 vibrato square ;
;3 vibrato sawtooth ;
;4 vibrato random ;
;5 tremola sine ;
;6 tremola triangle ;
;7 tremola square ;
;8 tremola sawtooth ;
;9 tremola random ;
;a halt note system ;
;b halt volume system ;
;c halt all systems ;
;d invert funkcrtl ;
;e algorithmic porting ;
;f linear porting ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc com_misccrtl
mov al,[byte edi+tfunk_chan.com_val]
and al,00001111b
or al,al
jz @@vib_sine
cmp al,01h
je @@vib_triangle
cmp al,02h
je @@vib_square
cmp al,03h
je @@vib_sawtooth
cmp al,04h
je @@vib_random
cmp al,05h
je @@trm_sine
cmp al,06h
je @@trm_triangle
cmp al,07h
je @@trm_square
cmp al,08h
je @@trm_sawtooth
cmp al,09h
je @@trm_random
cmp al,0ah
je @@halt_note_sys
cmp al,0bh
je @@halt_vol_sys
cmp al,0ch
je @@halt_all_sys
cmp al,0dh
je @@invert_funk
cmp al,0eh
je @@log_porta
cmp al,0fh
je @@lin_porta
ret
@@vib_sine:
mov [byte edi+tfunk_chan.vib_waveform],0
ret
@@vib_triangle:
mov [byte edi+tfunk_chan.vib_waveform],1
ret
@@vib_square:
mov [byte edi+tfunk_chan.vib_waveform],2
ret
@@vib_sawtooth:
mov [byte edi+tfunk_chan.vib_waveform],3
ret
@@vib_random:
mov [byte edi+tfunk_chan.vib_waveform],4
ret
@@trm_sine:
mov [byte edi+tfunk_chan.vol_vib_waveform],0
ret
@@trm_triangle:
mov [byte edi+tfunk_chan.vol_vib_waveform],1
ret
@@trm_square:
mov [byte edi+tfunk_chan.vol_vib_waveform],2
ret
@@trm_sawtooth:
mov [byte edi+tfunk_chan.vol_vib_waveform],3
ret
@@trm_random:
mov [byte edi+tfunk_chan.vol_vib_waveform],4
ret
@@halt_note_sys:
mov [byte edi+tfunk_chan.note_command],0fh
ret
@@halt_vol_sys:
mov [byte edi+tfunk_chan.volume_command],0fh
ret
@@halt_all_sys:
mov [byte edi+tfunk_chan.note_command],0fh
mov [byte edi+tfunk_chan.volume_command],0fh
ret
@@invert_funk:
xor [byte edi+tfunk_chan.funkctrl],1b
mov [byte edi+tfunk_chan.start],0
ret
@@log_porta:
mov [byte edi+tfunk_chan.port_type],0
ret
@@lin_porta:
mov [byte edi+tfunk_chan.port_type],1
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Com O1: volume cut ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc com_volume_cut
mov al,[byte edi+tfunk_chan.volume_com_val]
and al,1111b
cmp [byte edi+tfunk_chan.volume_comspd_count],al
jae @@speed_match
inc [byte edi+tfunk_chan.volume_comspd_count]
ret
@@speed_match:
mov [byte edi+tfunk_chan.volume_command],0fh
mov [byte edi+tfunk_chan.volume],0
call vol_to_realvol
call [dword CARD_volume_convert]
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Com O2: real frequency adjust ;
; ;
; - this adjustment is independant ;
; and is post added ;
; - this is a real frequency ;
; adjustment ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc com_real_freqad
mov al,[byte edi+tfunk_chan.com_val]
and eax,1111b
shl eax,3
mov [dword edi+tfunk_chan.rfreq_adjust],eax
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Com O3: set arpeggio speed ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc com_arp_speed_set
mov al,[byte edi+tfunk_chan.com_val]
and al,1111b
mov [byte edi+tfunk_chan.arp_speed],al
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Com O4: fine port_up ;
; ;
; com_val : 0000 ;
; \rate/ ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc com_fine_port_up
cmp [byte edi+tfunk_chan.port_type],1
je @@line_porta
call com_port_up_log
ret
@@line_porta:
call com_port_up_lin
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Com O5: fine port_dn ;
; ;
; com_val : 0000 ;
; \rate/ ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc com_fine_port_dn
cmp [byte edi+tfunk_chan.port_type],1
je @@line_porta
call com_port_dn_log
ret
@@line_porta:
call com_port_dn_lin
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Com O6: fine vol sld up ;
; ;
; com_val : 0000 ;
; \rate/ ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Com O7: fine vol sld dn ;
; ;
; com_val : 0000 ;
; \rate/ ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Com O8: volume crest ;
; ;
; com_val : 0000 ;
; \speed/ (prehand);
; ;
; volume slides up then down, ;
; starting at current frequency ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc com_vol_crest
mov bl,[byte edi+tfunk_chan.volume_com_val]
and ebx,1111b
mov dl,[byte ebx+com_volume_inc]
cmp [byte edi+tfunk_chan.volume_beat_count],1
je @@wait_a_bit
cmp [byte edi+tfunk_chan.volume_beat_count],2
je @@slide_down
add [byte edi+tfunk_chan.volume],dl
jc @@second_phase
@@done:
call vol_to_realvol
call [dword CARD_volume_convert]
ret
@@second_phase:
mov [byte edi+tfunk_chan.volume_comspd_count],0
inc [byte edi+tfunk_chan.volume_beat_count]
mov [byte edi+tfunk_chan.volume],0ffh
jmp @@done
@@wait_a_bit:
inc bl
neg bl
and bl,1111b
cmp [byte edi+tfunk_chan.volume_comspd_count],bl
jae @@speed_match
inc [byte edi+tfunk_chan.volume_comspd_count]
ret
@@speed_match:
mov [byte edi+tfunk_chan.volume_comspd_count],0
inc [byte edi+tfunk_chan.volume_beat_count]
ret
@@slide_down:
shr dl,2
inc dl
mov al,[byte edi+tfunk_chan.volume_portdest]
sub [byte edi+tfunk_chan.volume],dl
jc @@end
cmp [byte edi+tfunk_chan.volume],al
ja @@done
@@end:
mov [byte edi+tfunk_chan.volume_command],0fh
mov [byte edi+tfunk_chan.volume],al
jmp @@done
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Com O9: volume trough ;
; ;
; com_val : 0000 ;
; \speed/ (prehand);
; ;
; volume slides down then up, ;
; starting at current frequency ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc com_vol_trough
mov bl,[byte edi+tfunk_chan.volume_com_val]
and ebx,1111b
mov dl,[byte ebx+com_volume_inc]
cmp [byte edi+tfunk_chan.volume_beat_count],1
je @@wait_a_bit
cmp [byte edi+tfunk_chan.volume_beat_count],2
je @@slide_down
shr dl,2
inc dl
sub [byte edi+tfunk_chan.volume],dl
jc @@second_phase
@@done:
call vol_to_realvol
call [dword CARD_volume_convert]
ret
@@second_phase:
mov [byte edi+tfunk_chan.volume_comspd_count],0
inc [byte edi+tfunk_chan.volume_beat_count]
mov [byte edi+tfunk_chan.volume],0
jmp @@done
@@wait_a_bit:
inc bl
neg bl
and bl,1111b
cmp [byte edi+tfunk_chan.volume_comspd_count],bl
jae @@speed_match
inc [byte edi+tfunk_chan.volume_comspd_count]
ret
@@speed_match:
mov [byte edi+tfunk_chan.volume_comspd_count],0
inc [byte edi+tfunk_chan.volume_beat_count]
ret
@@slide_down:
mov al,[byte edi+tfunk_chan.volume_portdest]
add [byte edi+tfunk_chan.volume],dl
jc @@end
cmp [byte edi+tfunk_chan.volume],al
jb @@done
@@end:
mov [byte edi+tfunk_chan.volume_command],0fh
mov [byte edi+tfunk_chan.volume],al
jmp @@done
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Com OA: master volume set ;
; ;
; master effects all volumes, good ;
; for fading songs in and out ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc com_master_set
mov al,[byte edi+tfunk_chan.com_val]
and al,1111b
mov [byte funk_info.master_volume],al
push edi
lea edi,[funk_chan1]
mov cl,8
@@sync_volume:
push ecx
call [dword CARD_volume_convert]
add edi,size tfunk_chan
pop ecx
dec cl
jnz @@sync_volume
pop edi
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Com OB: expand loop ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc com_expand_loop
mov al,[byte edi+tfunk_chan.com_val]
and eax,1111b
inc al
mov cl,[byte edi+tfunk_chan.sample_ofs_parm]
shl eax,cl
sub [dword edi+tfunk_chan.start],eax
or [byte edi+tfunk_chan.funkctrl],10000000b
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Com OC: colapse loop ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc com_colapse_loop
mov al,[byte edi+tfunk_chan.com_val]
and eax,1111b
inc al
mov cl,[byte edi+tfunk_chan.sample_ofs_parm]
shl eax,cl
add [dword edi+tfunk_chan.start],eax
or [byte edi+tfunk_chan.funkctrl],10000000b
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Com OD: note retrig ;
; ;
; com_val : ???? 0000 ;
; \speed/ (prehand);
; ;
; command only handled on full ;
; or sample only slots ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc com_note_retrig
mov al,[byte edi+tfunk_chan.com_val]
and al,00001111b
cmp [byte edi+tfunk_chan.retrig_spd_count],al
jae @@speed_match
inc [byte edi+tfunk_chan.retrig_spd_count]
ret
@@speed_match:
mov [byte edi+tfunk_chan.retrig_spd_count],0
mov al,[byte edi+tfunk_chan.retrig_limit]
cmp [byte edi+tfunk_chan.retrig_count],al
jae @@done
inc [byte edi+tfunk_chan.retrig_count]
mov al,[byte edi+tfunk_chan.sample]
call do_retrig_sample
ret
@@done:
mov [byte edi+tfunk_chan.command],0fh
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Com OE: set channel balance ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc com_balance
mov al,[byte edi+tfunk_chan.com_val]
shl al,4
mov [byte edi+tfunk_chan.balance],al
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Com OF: tempo ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc com_tempo
mov al,[byte edi+tfunk_chan.com_val]
and al,1111b
mov [byte funk_info.tempo],al
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; Command control for null slots only ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc com_null_ctrl
mov eax,[dword edi+tfunk_chan.command]
and eax,1111111100001111b
cmp al,0fh
je @@command_idle
or al,al ; com a
je @@ns_basic
cmp al,01h ; com b
je @@ns_basic
cmp al,02h ; com c
je @@ns_basic
cmp al,03h ; com d
je @@ns_basic
cmp al,04h ; com e
je @@command_e
cmp al,05h ; com f
je @@command_f
cmp al,06h ; com g
je @@vs_basic
cmp al,07h ; com h
je @@vs_basic
cmp al,08h ; com i
je @@vs_basic
cmp al,09h ; com j
je @@command_j
cmp al,0ah ; com k
je @@vs_basic
cmp al,0bh ; com l
je @@command_l
cmp al,0dh ; com n
je @@command_n
mov ebx,eax
and bh,11110000b
cmp ebx,0000eh ; com o0
je @@command_o0
cmp ebx,0100eh ; com o1
je @@vs_basic
cmp ebx,0200eh ; com o2
je @@command_o2
cmp ebx,0300eh ; com o3
je @@command_o3
cmp ebx,0400eh ; com o4
je @@command_o4
cmp ebx,0500eh ; com o5
je @@command_o5
cmp ebx,0600eh ; com o6
je @@command_o6
cmp ebx,0700eh ; com o7
je @@command_o7
cmp ebx,0800eh ; com o8
je @@command_o8o9
cmp ebx,0900eh ; com o9
je @@command_o8o9
cmp ebx,0a00eh ; com oa
je @@command_oa
cmp ebx,0b00eh ; com ob
je @@command_ob
cmp ebx,0c00eh ; com oc
je @@command_oc
cmp ebx,0e00eh ; com oe
je @@command_oe
cmp ebx,0f00eh ; com of
je @@command_of
ret
@@ns_basic:
mov [word edi+tfunk_chan.note_command],ax
mov [byte edi+tfunk_chan.note_comspd_count],0
ret
@@vs_basic:
mov [word edi+tfunk_chan.volume_command],ax
mov [byte edi+tfunk_chan.volume_comspd_count],0
ret
@@command_e:
mov [byte edi+tfunk_chan.note_beat_count],0
jmp @@set_vib_fan
@@command_f:
mov [byte edi+tfunk_chan.note_beat_count],0fh
@@set_vib_fan:
cmp [byte edi+tfunk_chan.note_command],03h ; if vibrato command
jne @@dont_set_vib
mov bl,[byte edi+tfunk_chan.note_com_val]
shr bl,4
mov [byte edi+tfunk_chan.note_beat_count],bl
@@dont_set_vib:
mov [word edi+tfunk_chan.note_command],ax
mov [byte edi+tfunk_chan.note_comspd_count],0
ret
@@command_j:
mov [word edi+tfunk_chan.volume_command],ax
mov [byte edi+tfunk_chan.volume_comspd_count],0
mov al,[byte edi+tfunk_chan.volume]
mov [byte edi+tfunk_chan.volume_beat_count],al
ret
@@command_l:
mov [word edi+tfunk_chan.note_command],ax
mov [byte edi+tfunk_chan.note_comspd_count],0
mov [byte edi+tfunk_chan.note_beat_count],1
ret
@@command_n:
mov [word edi+tfunk_chan.volume_command],ax
call com_volume
ret
@@command_o0:
call com_misccrtl
ret
@@command_o2:
call com_real_freqad
call [dword CARD_volume_convert]
ret
@@command_o3:
call com_arp_speed_set
ret
@@command_o4:
mov [word edi+tfunk_chan.note_command],ax
call com_fine_port_up
ret
@@command_o5:
mov [word edi+tfunk_chan.note_command],ax
call com_fine_port_dn
ret
@@command_o6:
mov [word edi+tfunk_chan.volume_command],ax
call com_vol_up
ret
@@command_o7:
mov [word edi+tfunk_chan.volume_command],ax
call com_vol_dn
ret
@@command_o8o9:
mov [word edi+tfunk_chan.volume_command],ax
mov [byte edi+tfunk_chan.volume_comspd_count],0
mov [byte edi+tfunk_chan.volume_beat_count],0
mov al,[byte edi+tfunk_chan.volume]
mov [byte edi+tfunk_chan.volume_portdest],al
ret
@@command_oa:
call com_master_set
ret
@@command_ob:
call com_expand_loop
ret
@@command_oc:
call com_colapse_loop
ret
@@command_oe:
call com_balance
ret
@@command_of:
call com_tempo
ret
@@command_idle:
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; Command control for full slots ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc com_full_ctrl
mov eax,[dword edi+tfunk_chan.command]
and eax,1111111100001111b
cmp al,0fh
je @@command_idle
or al,al ; com a
je @@ns_basic
cmp al,01h ; com b
je @@ns_basic
cmp al,02h ; com c
je @@command_c
cmp al,03h ; com d
je @@ns_basic
cmp al,04h ; com e
je @@command_e
cmp al,05h ; com f
je @@command_f
cmp al,06h ; com g
je @@vs_basic
cmp al,07h ; com h
je @@vs_basic
cmp al,08h ; com i
je @@command_i
cmp al,09h ; com j
je @@command_j
cmp al,0ah ; com k
je @@vs_basic
cmp al,0bh ; com l
je @@command_l
cmp al,0ch ; com m
je @@command_m
cmp al,0dh ; com n
je @@command_n
mov ebx,eax
and bh,11110000b
cmp ebx,0000eh ; com o0
je @@command_o0
cmp ebx,0100eh ; com o1
je @@vs_basic
cmp ebx,0200eh ; com o2
je @@command_o2
cmp ebx,0300eh ; com o3
je @@command_o3
cmp ebx,0400eh ; com o4
je @@command_o4
cmp ebx,0500eh ; com o5
je @@command_o5
cmp ebx,0600eh ; com o6
je @@command_o6
cmp ebx,0700eh ; com o7
je @@command_o7
cmp ebx,0800eh ; com o8
je @@command_o8o9
cmp ebx,0900eh ; com o9
je @@command_o8o9
cmp ebx,0a00eh ; com oa
je @@command_oa
cmp ebx,0b00eh ; com ob
je @@command_ob
cmp ebx,0c00eh ; com oc
je @@command_oc
cmp ebx,0d00eh ; com od
je @@command_od
cmp ebx,0e00eh ; com oe
je @@command_oe
cmp ebx,0f00eh ; com of
je @@command_of
ret
@@ns_basic:
mov [word edi+tfunk_chan.note_command],ax
mov [byte edi+tfunk_chan.note_comspd_count],0
call normal_decode_note
ret
@@vs_basic:
mov [word edi+tfunk_chan.volume_command],ax
mov [byte edi+tfunk_chan.volume_comspd_count],0
call normal_decode_volume
ret
@@command_c:
mov [word edi+tfunk_chan.note_command],ax
mov [byte edi+tfunk_chan.note_comspd_count],0
call comc_decode
ret
@@command_e:
mov [byte edi+tfunk_chan.note_beat_count],0
jmp @@set_vib_fan
@@command_f:
mov [byte edi+tfunk_chan.note_beat_count],0fh
@@set_vib_fan:
cmp [byte edi+tfunk_chan.note_command],03h ; if vibrato command
jne @@dont_set_vib
mov bl,[byte edi+tfunk_chan.note_com_val]
shr bl,4
mov [byte edi+tfunk_chan.note_beat_count],bl
@@dont_set_vib:
mov [word edi+tfunk_chan.note_command],ax
mov [byte edi+tfunk_chan.note_comspd_count],0
call normal_decode_note
ret
@@command_i:
mov [word edi+tfunk_chan.volume_command],ax
mov [byte edi+tfunk_chan.volume_comspd_count],0
call comi_decode
ret
@@command_j:
mov [word edi+tfunk_chan.volume_command],ax
mov [byte edi+tfunk_chan.volume_comspd_count],0
call normal_decode_volume
mov al,[byte edi+tfunk_chan.volume]
mov [byte edi+tfunk_chan.volume_beat_count],al
ret
@@command_l:
mov [word edi+tfunk_chan.note_command],ax
mov [byte edi+tfunk_chan.note_comspd_count],0
mov [byte edi+tfunk_chan.note_beat_count],1
call normal_decode_note
ret
@@command_m:
call normal_decode_system
call com_sample_offset
ret
@@command_n:
mov [word edi+tfunk_chan.volume_command],ax
call normal_decode_volume
call com_volume
ret
@@command_o0:
call normal_decode_system
call com_misccrtl
ret
@@command_o2:
call com_real_freqad
call normal_decode_system
ret
@@command_o3:
call normal_decode_system
call com_arp_speed_set
ret
@@command_o4:
mov [word edi+tfunk_chan.note_command],ax
call normal_decode_note
call com_fine_port_up
ret
@@command_o5:
mov [word edi+tfunk_chan.note_command],ax
call normal_decode_note
call com_fine_port_dn
ret
@@command_o6:
mov [word edi+tfunk_chan.volume_command],ax
call normal_decode_volume
call com_vol_up
ret
@@command_o7:
mov [word edi+tfunk_chan.volume_command],ax
call normal_decode_volume
call com_vol_dn
ret
@@command_o8o9:
mov [word edi+tfunk_chan.volume_command],ax
mov [byte edi+tfunk_chan.volume_comspd_count],0
mov [byte edi+tfunk_chan.volume_beat_count],0
call normal_decode_volume
mov al,[byte edi+tfunk_chan.volume]
mov [byte edi+tfunk_chan.volume_portdest],al
ret
@@command_oa:
call com_master_set
call normal_decode_system
ret
@@command_ob:
call normal_decode_system
call com_expand_loop
ret
@@command_oc:
call normal_decode_system
call com_colapse_loop
ret
@@command_od:
mov [byte edi+tfunk_chan.retrig_count],1
mov [byte edi+tfunk_chan.retrig_spd_count],0
call normal_decode_system
ret
@@command_oe:
call normal_decode_system
call com_balance
ret
@@command_of:
call normal_decode_system
call com_tempo
ret
@@command_idle:
call normal_decode_system
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; Command control for rapid "on the fly" ;
; Rapid commands that have a speed parameter ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc com_rapid_ctrl
lea edi,[funk_chan1]
mov cl,8
@@play_slot:
push ecx
call note_system_rapid_p1
call volume_system_rapid_p1
mov eax,[dword edi+tfunk_chan.note_command]
cmp al,03h ; command d
je @@command_d
cmp al,04h ; command e
je @@command_e
cmp al,05h ; command f
je @@command_f
cmp al,0bh ; command l
je @@command_l
jmp @@do_vol_com
@@command_d:
call com_vibrato
jmp @@do_vol_com
@@command_e:
call com_vib_fanin
jmp @@do_vol_com
@@command_f:
call com_vib_fanout
jmp @@do_vol_com
@@command_l:
call com_arpeggio
@@do_vol_com:
mov eax,[dword edi+tfunk_chan.volume_command]
cmp al,09h ; command j
je @@command_j
cmp al,0Ah ; command k
je @@command_k
and eax,1111000000001111b
cmp eax,0100eh ; command o1
je @@command_o1
cmp eax,0800eh ; command o8
je @@command_o8
cmp eax,0900eh ; command o9
je @@command_o9
jmp @@system_final
@@command_j:
call com_reverb
jmp @@system_final
@@command_k:
call com_tremola
jmp @@system_final
@@command_o1:
call com_volume_cut
jmp @@system_final
@@command_o8:
call com_vol_crest
jmp @@system_final
@@command_o9:
call com_vol_trough
@@system_final:
mov eax,[dword edi+tfunk_chan.command]
and eax,1111000000001111b
cmp eax,0d00eh ; command od
jne @@end_command
call com_note_retrig
@@end_command:
pop ecx
add edi,size tfunk_chan
dec cl
jnz @@play_slot
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; ESI = current pattern ;
; ;
; format: ;
; ;
; 00000000 11111111 22222222 ;
; \ /\ /\ / \ / ;
; note sample com command value ;
; ;
; - if note: = 3D, then reload sample attrs ;
; = 3F, then it's a null slot ;
; = 3E, then sample only slot ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc trekk_slot
movzx eax,[byte funk_info.pattern_ofs] ;24 * al
mov ebx,eax
shl eax,4
shl ebx,3
add eax,ebx
add esi,eax
lea edi,[funk_chan1]
mov cl,8
@@play_slot:
push ecx esi
mov ax,[word esi+1] ;extract command and value
and al,00001111b
mov [word edi+tfunk_chan.command],ax
mov al,[byte esi]
shr al,2
cmp al,03Fh ;IF FULL SLOT or SAMPLE
jne @@full_cont ;ONLY SLOT
call com_null_ctrl
jmp @@next_channel
@@full_cont:
call com_full_ctrl
@@next_channel:
pop esi ecx
add edi,size tfunk_chan
add esi,3
dec cl
jnz @@play_slot
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; The actual tracker thingy :) ....0.02 second tick (or roughly) ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc funk_tracker
cmp [byte funk_info.trek_status],STOP
je @@dont_play
call com_rapid_ctrl
mov al,[byte funk_info.tempo]
cmp [byte funk_info.tempo_count],al
jb @@tempo_miss
mov [byte funk_info.tempo_count],0
xor ebx,ebx
mov bl,[byte funk_info.sequence_ofs]
mov edi,[funk_hr_ptr]
movzx esi,[byte ebx+edi+tfunk_hr.order_list]
mov eax,esi ; bx * 600h
shl eax,10
shl esi,9
add esi,eax
add esi,edi
add esi,size tfunk_hr
call trekk_slot
mov edi,[funk_hr_ptr]
xor ebx,ebx
mov bl,[byte funk_info.sequence_ofs]
movzx ebx,[byte ebx+edi+tfunk_hr.order_list]
mov al,[byte ebx+edi+tfunk_hr.break_list]
cmp [byte funk_info.pattern_ofs],al ;if done last pattern then...
je @@change_pattern ;jump if no pattern cross
inc [byte funk_info.pattern_ofs] ;add the trek slot ofs
ret
@@change_pattern:
mov cl,[byte funk_info.no_of_sequences]
cmp [byte funk_info.sequence_ofs],cl
jb @@dont_loop_seq_ofs
cmp [byte edi+tfunk_hr.loop_order],0FFh
jne @@set_loop_rippp
mov [byte funk_info.trek_status],STOP
@@set_loop_rippp:
mov dl,[byte edi+tfunk_hr.loop_order]
dec dl
mov [byte funk_info.sequence_ofs],dl
@@dont_loop_seq_ofs:
inc [byte funk_info.sequence_ofs]
mov [byte funk_info.pattern_ofs],0
ret
@@tempo_miss:
inc [byte funk_info.tempo_count]
@@dont_play:
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc stop_all_voices
cli
lea edi,[funk_chan1]
xor cl,cl
@@play_slot:
push ecx
mov [byte edi+tfunk_chan.funkctrl],0
mov [byte edi+tfunk_chan.volume],0
mov [byte edi+tfunk_chan.rvolume],0
call [dword CARD_volume_convert]
pop ecx
add edi,size tfunk_chan
inc cl
cmp cl,8
jb @@play_slot
sti
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; MPU-401 UART Code (Midi keyboard code) ;
; ;
; (NB/ most of the MPU code is from the CT SDK kit V2.0) ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MPU_addr dd 330h
struc tMIDI
midi_status db STOP
midi_buffer db 32 dup(?) ; 32 byte circulur buffer
midi_buffer_head dd 0
midi_buffer_tail dd 0
base db 0
byte1 db 0
byte2 db 0
byte3 db 0
ends
MIDI tMIDI <>
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc MIDI_queue_in
mov ebx,[MIDI.midi_buffer_head]
mov [byte ebx+MIDI.midi_buffer],al
inc [MIDI.midi_buffer_head]
and [MIDI.midi_buffer_head],31
ret
endp
proc MIDI_queue_out_pol
@@wait:
mov ebx,[MIDI.midi_buffer_tail]
cmp ebx,[MIDI.midi_buffer_head]
je @@wait
mov al,[byte ebx+MIDI.midi_buffer]
inc [MIDI.midi_buffer_tail]
and [MIDI.midi_buffer_tail],31
ret
endp
proc MIDI_queue_out_sig
mov ebx,[MIDI.midi_buffer_tail]
cmp ebx,[MIDI.midi_buffer_head]
je @@ignore
mov al,[byte ebx+MIDI.midi_buffer]
inc [MIDI.midi_buffer_tail]
and [MIDI.midi_buffer_tail],31
clc
ret
@@ignore:
stc
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ResetMPU401 ;
; Reset MPU-401 (for SB16 only) ;
; Entry : ;
; none. ;
; Exit : ;
; EAX = 0 if successful else 1. ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc MPU401_Reset
cli
mov edx,[MPU_addr]
inc edx
xor ecx,ecx
@@Busy1:
in al,dx
test al,40h
jz @@ok1
dec cx
jnz @@Busy1
jmp @@fail
@@ok1:
mov al,0FFh
out dx,al
sub ecx,ecx
@@Empty1:
in al,dx
test al,80h
jnz @@NesLoop1
dec edx
in al,dx
cmp al,0FEh
mov eax,00h
je @@ResetOK1
inc edx
@@NesLoop1:
dec cx
jnz @@Empty1
@@fail:
mov eax,01H
@@ResetOK1:
sti
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; EnterUARTModeMPU401 ;
; Set MPU-401 to UART mode. ;
; Entry : ;
; none. ;
; Exit : ;
; EAX = 0 if successful else 1. ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc MPU401_EUARTM
cli
mov edx,[MPU_addr]
inc edx
@@Busy2:
in al,dx
test al,40h
jnz @@Busy2
mov al,3Fh
out dx,al
sub ecx,ecx
@@Empty2:
in al,dx
test al,80h
jnz @@NesLoop2
dec edx
in al,dx
cmp al,0FEh
je @@InUartMode2
inc edx
@@NesLoop2:
dec cx
jnz @@Empty2
mov eax,01h
jmp @@exit
@@InUartMode2:
mov eax,00h
@@exit:
sti
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WriteMPU401 ;
; Write a byte of MIDI data to MPU-401 ;
; Entry : ;
; al = output data. ;
; Exit : ;
; none. ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc MPU401_Write
cli
push edx
mov edx,[MPU_addr]
inc edx
push eax
@@Busy3:
in al,dx
test al,40h
jnz @@Busy3
dec edx
pop eax
out dx,al
pop edx
sti
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ReadMPU401 ;
; Read a byte of MIDI data from MPU-401 ;
; Entry : ;
; none. ;
; Exit : ;
; al = input data. ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc MPU401_Read
cli
push edx
mov edx,[MPU_addr]
inc edx
@@Busy4:
in al,dx
test al,80H
jnz @@Busy4
dec edx
in al,dx
pop edx
sti
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; DMA routines (From DOS32) ;
; INPUT: AL Mode Register ( bits 0..1 ignored ) ;
; AH channel 0..7 ;
; EBX Physical Base Address ;
; ECX Bytes to transfer ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc DMA_Setup
xor edx,edx
and ah,7
mov [@@DMA_channel],ah
and al,NOT 3
mov [@@mode],al
movzx edi,[byte @@DMA_channel]
mov eax,edi
shr edi,2
and al,0011b
or al,0100b
mov dl,[edi+@@DMA_SNGL]
out dx,al
call @@pause
and al,03h
or al,[@@Mode]
mov dl,[edi+@@DMA_MODE]
out dx,al
call @@pause
mov dl,[edi+@@DMA_CLRFF]
out dx,al
call @@pause
movzx edi,[@@DMA_channel]
mov eax,ecx
mov ecx,edi
shr ecx,2
shr eax,cl
mov dl,[edi+@@DMA_CNT]
out dx,al
call @@pause
shr eax,8
out dx,al
call @@pause
shr ebx,cl
mov al,BL
mov dl,[edi+@@DMA_ADDR]
out dx,al
call @@pause
mov al,BH
out dx,al
call @@pause
shr ebx,15
xor cl,1
shr ebx,cl
mov al,BL
mov dl,[edi+@@DMA_PAGE]
out dx,al
call @@pause
mov eax,edi
shr edi,2
and al,03h
mov dl,[edi+@@DMA_SNGL]
out dx,al
call @@pause
ret
@@Mode db ?
@@DMA_Channel db ?
@@DMA_STAT db 008h,0D0h
@@DMA_CMD db 008h,0D0h
@@DMA_REQ db 009h,0D2h
@@DMA_SNGL db 00Ah,0D4h
@@DMA_MODE db 00Bh,0D6h
@@DMA_CLRFF db 00Ch,0D8h
@@DMA_MCLR db 00Dh,0DAh
@@DMA_CLRM db 00Eh,0DCh
@@DMA_WRTALL db 00Fh,0DEh
@@DMA_PAGE db 087h,083h,081h,082h,08Fh,08Bh,089h,08Ah
@@DMA_ADDR db 000h,002h,004h,006h,0C0h,0C4h,0C8h,0CCh
@@DMA_CNT db 001h,003h,005h,007h,0C2h,0C6h,0CAh,0CEh
proc @@pause
jmp @@j
@@j:
ret
endp
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; DAC INDEPENDANT CODE ;
; ;
; These routines are general DAC routines used by all DAC soundcards. ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DAC_old_irq_ofs dd 0
DAC_old_irq_sel dw 0
DAC_mix_buffer_size dd ?
DAC_sampling_rate dd ?
DMA_length dd 4000h
DAC_mb_offs = 0
DAC_mb_right_offs = 1000h
DAC_mb2_offs = 2000h
DAC_mix_buffer dd DAC_mb_offs
DAC_mix_buffer_right dd DAC_mb_right_offs
DAC_mix_buffer2 dd DAC_mb2_offs
DAC_PHYSICAL_PAGE dd DAC_mb2_offs
DAC_shift_value db 0
DAC_double_buf1 dd 0
DAC_double_buf2 dd 0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc DACi_freq_convert
mov eax,[dword edi+tfunk_chan.rfreq]
mov edx,eax
shl eax,16
shr edx,16
div [dword DAC_sampling_rate]
mov [dword edi+tfunk_chan.CARD_freq],eax
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc DACi_volume_convert
xor eax,eax
cmp [byte edi+tfunk_chan.channel_kill],STOP
je @@transt
mov al,[byte funk_info.master_volume]
cmp al,0
je @@transt
xor ecx,ecx
mov cl,[byte edi+tfunk_chan.rvolume]
inc al
mul ecx
mov cl,[byte DAC_shift_value]
shr eax,cl
@@transt:
mov [byte edi+tfunk_chan.CARD_volume],al
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; unit channel DAC buffer Mixer ;
; ;
; ebx = channel ptr, edi = buffer ;
; ;
; 00 ;
; ||_____ 1=loop sample ;
; | ;
; |______ DAC sample play ;
; ;
; ===================================================================== ;
; ;
; This is the heart of DAC mixxing. Here we actually mix a given channel ;
; to the mixing buffer. This code does frequency transformations and volume;
; manipulation (it's what the DSP cards do interally). If a Card does this ;
; in hardware, then it is refered to as a "DSP" card rather than a "DAC" ;
; card. An example of a "DSP" card is the Gravis Ultrasound card. ;
; ;
; The frequency transformer belongs to Tom Verbeure...thanks tom! ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc DAC_channel_mixxer
mov ch,[byte ebx+tfunk_chan.funkctrl]
mov cl,[byte ebx+tfunk_chan.CARD_volume]
mov edx,[dword ebx+tfunk_chan.CARD_freq]
mov ebp,edx
shl edx,16
shr ebp,16
mov esi,[dword ebx+tfunk_chan.CARD_sample_ptr]
mov eax,[dword DAC_mix_buffer_size]
@@mix_loop:
push eax
test ch,10b
jnz @@run_sample
xor al,al
jmp @@trans_sample
@@run_sample:
mov al,[byte esi]
@@trans_sample:
imul cl
add [word edi],ax
add edi,2
add [dword ebx+tfunk_chan.CARD_freq_attract],edx
adc esi,ebp
cmp esi,[dword ebx+tfunk_chan.length]
jb @@comp_end
test ch,01b
jnz @@loop_back
and ch,01b
jmp @@comp_end
@@loop_back:
mov esi,[dword ebx+tfunk_chan.start]
@@comp_end:
pop eax
dec eax
jnz @@mix_loop
mov [byte ebx+tfunk_chan.funkctrl],ch
mov [dword ebx+tfunk_chan.CARD_sample_ptr],esi
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; SB DEPENDANT CODE ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SB_INTR_8BITDMA = 1
SB_INTR_16BITDMA = 2
SB_INTR_MPU401 = 4
SB_BASE dd ?
SB_MIXER dd ?
SB_RESET dd ?
SB_READ_DATA dd ?
SB_WRITE_DATA dd ?
SB_DATA_AVAIL dd ?
SB_DATA_AVAIL16 dd ?
SB_trig dd ?
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc SB_detect_port
mov eax,[dword init_settings.PORT_no]
mov [dword SB_BASE],0
mov [dword SB_MIXER],4h
mov [dword SB_RESET],6h
mov [dword SB_READ_DATA],0ah
mov [dword SB_WRITE_DATA],0ch
mov [dword SB_DATA_AVAIL],0eh
mov [dword SB_DATA_AVAIL16],0fh
add [dword SB_BASE],eax
add [dword SB_MIXER],eax
add [dword SB_RESET],eax
add [dword SB_READ_DATA],eax
add [dword SB_WRITE_DATA],eax
add [dword SB_DATA_AVAIL],eax
add [dword SB_DATA_AVAIL16],eax
lea eax,[DACi_freq_convert]
mov [dword CARD_freq_convert],eax
lea eax,[DACi_volume_convert]
mov [dword CARD_volume_convert],eax
mov al,1
mov edx,[dword SB_RESET]
out dx,al
in al,dx
in al,dx
in al,dx
in al,dx
xor al,al
mov edx,[dword SB_RESET]
out dx,al
mov cl,64h
@@DataWait:
mov edx,[dword SB_DATA_AVAIL]
in al,dx
test al,80h
jnz @@YesData
dec cl
jnz @@DataWait
jmp @@exit
@@YesData:
mov edx,[dword SB_READ_DATA]
in al,dx
cmp al,0AAh
je @@YepSB
dec cl
jnz @@DataWait
jmp @@exit
@@YepSB:
clc
ret
@@exit:
stc
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc SB_write_dac
push eax
mov edx,[dword SB_WRITE_DATA]
@@Wait_Ready:
in al,dx
and al,80h
jnz @@Wait_Ready
pop eax
out dx,al
ret
endp
proc SB_read_dac
mov edx,[dword SB_DATA_AVAIL]
@@Wait_Ready:
in al,dx
or al,al
jns @@Wait_Ready
sub edx,4
in al,dx
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; al = addr ah = data SBPRO mixxer ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc SB_write_mixer
mov edx,[dword SB_MIXER]
push edx
out dx,al
pop edx
inc edx
mov al,ah
out dx,al
ret
endp
proc SB_read_mixer
mov edx,[dword SB_MIXER]
push edx
out dx,al
pop edx
inc edx
in al,dx
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; DMA trigs ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc SB_trig_compatable
mov al,14h ;DMA_8_BIT_DAC
call SB_write_dac
mov eax,[dword DMA_length]
dec eax
call SB_write_dac
mov al,ah
call SB_write_dac
ret
endp
proc SB_trig_advanced
mov al,91h
call SB_write_dac
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc SB_virtualmixxer
cld
push ds es
pushad
mov ax,DGROUP
mov ds,ax
mov es,ax
mov edx,[dword SB_DATA_AVAIL]
in al,dx
call [dword SB_trig]
mov esi,[dword DAC_mix_buffer]
mov edi,[dword DAC_mix_buffer2]
add edi,[DAC_double_buf1]
mov eax,[DAC_double_buf1]
xchg eax,[DAC_double_buf2]
mov [DAC_double_buf1],eax
mov ecx,[dword DAC_mix_buffer_size]
shr ecx,1
@@trans8:
mov eax,[esi]
mov al,ah
mov [edi],al
mov eax,[esi+2]
mov al,ah
mov [edi+1],al
add esi,4
add edi,2
dec ecx
jnz @@trans8
call funk_tracker
mov ecx,[dword DAC_mix_buffer_size]
shr ecx,1
mov edi,[dword DAC_mix_buffer]
mov eax,80008000h
rep stosd
lea ebx,[funk_chan1]
mov edi,[dword DAC_mix_buffer]
call DAC_channel_mixxer
lea ebx,[funk_chan2]
mov edi,[dword DAC_mix_buffer]
call DAC_channel_mixxer
lea ebx,[funk_chan3]
mov edi,[dword DAC_mix_buffer]
call DAC_channel_mixxer
lea ebx,[funk_chan4]
mov edi,[dword DAC_mix_buffer]
call DAC_channel_mixxer
lea ebx,[funk_chan5]
mov edi,[dword DAC_mix_buffer]
call DAC_channel_mixxer
lea ebx,[funk_chan6]
mov edi,[dword DAC_mix_buffer]
call DAC_channel_mixxer
lea ebx,[funk_chan7]
mov edi,[dword DAC_mix_buffer]
call DAC_channel_mixxer
lea ebx,[funk_chan8]
mov edi,[dword DAC_mix_buffer]
call DAC_channel_mixxer
mov al,20h
out 20h,al
popad
pop es ds
iretd
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc SBPRO_virtualmixxer
cld
push ds es
pushad
mov ax,DGROUP
mov ds,ax
mov es,ax
mov edx,[dword SB_DATA_AVAIL]
in al,dx
call [dword SB_trig]
mov esi,[dword DAC_mix_buffer]
mov edi,[dword DAC_mix_buffer2]
add edi,[DAC_double_buf1]
mov eax,[DAC_double_buf1]
xchg eax,[DAC_double_buf2]
mov [DAC_double_buf1],eax
mov ecx,[dword DAC_mix_buffer_size]
shr ecx,1
@@trans8:
mov eax,[esi+DAC_mb_right_offs]
mov al,ah
mov ah,[byte esi+1+DAC_mb_offs]
mov [edi],ax
mov eax,[esi+2+DAC_mb_right_offs]
mov al,ah
mov ah,[byte esi+3+DAC_mb_offs]
mov [edi+2],ax
add esi,4
add edi,4
dec ecx
jnz @@trans8
call funk_tracker
mov ecx,[dword DAC_mix_buffer_size]
shr ecx,1
mov edi,[dword DAC_mix_buffer]
mov eax,80008000h
rep stosd
mov ecx,[dword DAC_mix_buffer_size]
shr ecx,1
mov edi,[dword DAC_mix_buffer_right]
rep stosd
lea ebx,[funk_chan1]
mov edi,[dword DAC_mix_buffer]
call DAC_channel_mixxer
lea ebx,[funk_chan2]
mov edi,[dword DAC_mix_buffer_right]
call DAC_channel_mixxer
lea ebx,[funk_chan3]
mov edi,[dword DAC_mix_buffer]
call DAC_channel_mixxer
lea ebx,[funk_chan4]
mov edi,[dword DAC_mix_buffer_right]
call DAC_channel_mixxer
lea ebx,[funk_chan5]
mov edi,[dword DAC_mix_buffer]
call DAC_channel_mixxer
lea ebx,[funk_chan6]
mov edi,[dword DAC_mix_buffer_right]
call DAC_channel_mixxer
lea ebx,[funk_chan7]
mov edi,[dword DAC_mix_buffer]
call DAC_channel_mixxer
lea ebx,[funk_chan8]
mov edi,[dword DAC_mix_buffer_right]
call DAC_channel_mixxer
mov al,20h
out 20h,al
popad
pop es ds
iretd
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc SB16_virtualmixxer
cld
push ds es
pushad
mov ax,DGROUP
mov ds,ax
mov es,ax
@@Poll:
mov edx,[SB_MIXER]
mov al,82h
out dx,al
inc edx
in al,dx
test al,02h
jnz @@SB16_DSP_ISA
test al,04h
jnz @@MPU_401_ISA
jmp @@chainpreviousISR
@@SB16_DSP_ISA:
mov edx,[dword SB_DATA_AVAIL16]
in al,dx
mov esi,[dword DAC_mix_buffer]
mov edx,[dword DAC_mix_buffer_right]
mov edi,[dword DAC_mix_buffer2]
add edi,[DAC_double_buf1]
mov eax,[DAC_double_buf1]
xchg eax,[DAC_double_buf2]
mov [DAC_double_buf1],eax
mov ecx,[dword DAC_mix_buffer_size]
xor ebx,ebx
@@trans16:
mov eax,[edx+ebx]
shl eax,16
mov ax,[word esi+ebx]
mov [edi+ebx*2],eax
add ebx,2
dec ecx
jnz @@trans16
call funk_tracker
mov ecx,[dword DAC_mix_buffer_size]
shr ecx,1
mov edi,[dword DAC_mix_buffer]
xor eax,eax
rep stosd
mov ecx,[dword DAC_mix_buffer_size]
shr ecx,1
mov edi,[dword DAC_mix_buffer_right]
rep stosd
lea ebx,[funk_chan1]
mov edi,[dword DAC_mix_buffer]
call DAC_channel_mixxer
lea ebx,[funk_chan2]
mov edi,[dword DAC_mix_buffer_right]
call DAC_channel_mixxer
lea ebx,[funk_chan3]
mov edi,[dword DAC_mix_buffer]
call DAC_channel_mixxer
lea ebx,[funk_chan4]
mov edi,[dword DAC_mix_buffer_right]
call DAC_channel_mixxer
lea ebx,[funk_chan5]
mov edi,[dword DAC_mix_buffer]
call DAC_channel_mixxer
lea ebx,[funk_chan6]
mov edi,[dword DAC_mix_buffer_right]
call DAC_channel_mixxer
lea ebx,[funk_chan7]
mov edi,[dword DAC_mix_buffer]
call DAC_channel_mixxer
lea ebx,[funk_chan8]
mov edi,[dword DAC_mix_buffer_right]
call DAC_channel_mixxer
jmp @@Poll
@@MPU_401_ISA:
call MPU401_Read
call MIDI_queue_in
jmp @@Poll
@@chainpreviousISR:
@@ExitISR:
mov al,20h
out 20h,al
popad
pop es ds
iretd
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
label SB_sample_settings tDAC_ssetings
tDAC_ssetings <11025,00222,222,11200>
tDAC_ssetings <16538,00332,332,16538>
tDAC_ssetings <22050,00442,442,22050>
tDAC_ssetings <33075,00662,662,33075>
tDAC_ssetings <44100,00882,882,44100>
proc SB_init_compatable
mov eax,offset SB_trig_compatable
mov [SB_trig],eax
movzx eax,[byte init_settings.DAC_Samplerate]
mov ecx,size tDAC_ssetings
mul ecx
mov [byte DAC_shift_value],7
mov ebx,[dword eax+SB_sample_settings.DAC_sr]
mov [dword DAC_sampling_rate],ebx
mov ebx,[dword eax+SB_sample_settings.DAC_mix_buffer_size]
mov [dword DAC_mix_buffer_size],ebx
mov ebx,[dword eax+SB_sample_settings.DMA_length]
mov [dword DMA_length],ebx
mov eax,[dword eax+SB_sample_settings.DMA_real_sr]
push eax
mov bl,[byte init_settings.IRQ_no]
lea edx,[SB_virtualmixxer]
mov cx,cs
call setirqvector
xor edx,edx ;set sampling rate
mov eax,1000000
pop ecx
div ecx
neg al
push eax
mov al,40h ;TIME_CONSTANT
call SB_write_dac
pop eax
call SB_write_dac
mov al,0D1h ;SPEAKER_ON
call SB_write_dac
cli
in al,21h
mov bl,1
mov cl,[byte init_settings.IRQ_no]
shl bl,cl
not bl
and al,bl
out 21h,al
mov al,01011000b ;DMA remote-init
mov ah,[byte init_settings.DMA_no]
mov ebx,[dword DAC_PHYSICAL_PAGE]
mov ecx,[dword DMA_length]
dec ecx
call DMA_setup
call SB_trig_compatable
sti
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
label SBPRO_sample_settings tDAC_ssetings ; NB/ SBPRO can't do more than 22050
tDAC_ssetings <11025,00222,0444,23000>
tDAC_ssetings <16538,00332,0664,35000>
tDAC_ssetings <22050,00442,0884,88200>
tDAC_ssetings <22050,00442,0884,88200>
tDAC_ssetings <22050,00442,0884,88200>
proc sb_init_advanced
mov eax,offset SB_trig_advanced
mov [SB_trig],eax
movzx eax,[byte init_settings.DAC_Samplerate]
mov ecx,size tDAC_ssetings
mul ecx
cmp [byte init_settings.card_type],SBPRO_CARD
je @@set_for_SBPRO
mov [byte DAC_shift_value],7
mov ebx,[dword eax+SB_sample_settings.DAC_sr]
mov [dword DAC_sampling_rate],ebx
mov ebx,[dword eax+SB_sample_settings.DAC_mix_buffer_size]
mov [dword DAC_mix_buffer_size],ebx
mov [DAC_double_buf2],ebx
mov ebx,[dword eax+SB_sample_settings.DMA_length]
mov [dword DMA_length],ebx
mov eax,[dword eax+SB_sample_settings.DMA_real_sr]
push eax
mov bl,[byte init_settings.IRQ_no]
lea edx,[SB_virtualmixxer]
mov cx,cs
call setirqvector
xor edx,edx ;set sampling rate
mov eax,256000000
pop ecx
div ecx
mov ebx,0ffffh
sub ebx,eax
shr ebx,8
push ebx
jmp @@done_set
@@set_for_SBPRO:
push eax
mov [byte DAC_shift_value],6
;-SETUP_PRO MIXXER SETTINGS---------
mov eax,00000h ;reset mixxer first
call SB_write_mixer
mov eax,0020eh
call SB_write_mixer
mov eax,0ff22h ;set Master volume
call SB_write_mixer
mov eax,0ff04h ;set DSP volume
call SB_write_mixer
;-SETUP_PRO MIXXER SETTINGS---------
pop eax
mov ebx,[dword eax+SBPRO_sample_settings.DAC_sr]
mov [dword DAC_sampling_rate],ebx
mov ebx,[dword eax+SBPRO_sample_settings.DAC_mix_buffer_size]
mov [dword DAC_mix_buffer_size],ebx
lea ebx,[ebx*2]
mov [DAC_double_buf2],ebx
mov ebx,[dword eax+SBPRO_sample_settings.DMA_length]
mov [dword DMA_length],ebx
mov eax,[dword eax+SBPRO_sample_settings.DMA_real_sr]
push eax
mov bl,[byte init_settings.IRQ_no]
lea edx,[SBPRO_virtualmixxer]
mov cx,cs
call setirqvector
xor edx,edx ;set sampling rate
mov eax,256000000
pop ecx
div ecx
mov ebx,0ffffh
sub ebx,eax
shr ebx,8
push ebx
@@done_set:
mov al,40h ;TIME_CONSTANT
call SB_write_dac
pop eax
call SB_write_dac
mov al,0D1h ;SPEAKER_ON
call SB_write_dac
cli
in al,21h
mov bl,1
mov cl,[byte init_settings.IRQ_no]
shl bl,cl
not bl
and al,bl
out 21h,al
mov al,01011000b ;DMA remote-init
mov ah,[byte init_settings.DMA_no]
mov ebx,[dword DAC_PHYSICAL_PAGE]
mov ecx,[dword DMA_length]
lea ecx,[ecx*2]
dec ecx
call DMA_setup
mov al,48h ;DMA_8_BIT_DAC (FAST)
call SB_write_dac
mov eax,[dword DMA_length]
dec eax
call SB_write_dac
mov al,ah
call SB_write_dac
mov al,91h
call SB_write_dac
sti
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc SB08_init
mov bl,[byte init_settings.IRQ_no]
call getirqvector
mov [dword DAC_old_irq_ofs],edx
mov [word DAC_old_irq_sel],cx
cmp [byte init_settings.card_type],SB_CARD
je @@set_advanced
cmp [byte init_settings.card_type],SBPRO_CARD
je @@set_advanced
cmp [byte init_settings.card_type],SB15EM_CARD
je @@set_compatable
ret
@@set_compatable:
call sb_init_compatable
ret
@@set_advanced:
call sb_init_advanced
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; SB1.X, SB2,0 + SBPRO deinit ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc sbsub1_deinit
mov bl,1
mov cl,[byte init_settings.IRQ_no]
shl bl,cl
in al,21h
or al,bl
out 21h,al
mov bl,[byte init_settings.IRQ_no]
mov edx,[dword DAC_old_irq_ofs]
mov cx,[word DAC_old_irq_sel]
call setirqvector
ret
endp
proc SB08_deinit
call SB_detect_port
cmp [byte init_settings.card_type],SBPRO_CARD
jne @@dont_reset
mov eax,110eh ;set for mono
call SB_write_mixer
@@dont_reset:
mov al,0D0h ;HALT_DMA
call SB_write_dac
cli
call sbsub1_deinit
sti
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
label SB16_sample_settings tDAC_ssetings
tDAC_ssetings <11025,00222,0444,011400>
tDAC_ssetings <16538,00332,0664,017400>
tDAC_ssetings <22050,00442,0884,088200>
tDAC_ssetings <33075,00662,1324,165000>
tDAC_ssetings <44100,00882,1764,176400>
proc SB16_init
mov bl,[byte init_settings.IRQ_no]
call getirqvector
mov [dword DAC_old_irq_ofs],edx
mov [word DAC_old_irq_sel],cx
mov bl,[byte init_settings.IRQ_no]
lea edx,[SB16_virtualmixxer]
mov cx,cs
call setirqvector
mov [byte DAC_shift_value],6
movzx eax,[byte init_settings.DAC_Samplerate]
mov ecx,size tDAC_ssetings
mul ecx
mov ebx,[dword eax+SB16_sample_settings.DAC_sr]
mov [dword DAC_sampling_rate],ebx
mov ebx,[dword eax+SB16_sample_settings.DAC_mix_buffer_size]
mov [dword DAC_mix_buffer_size],ebx
lea ebx,[ebx*4]
mov [DAC_double_buf2],ebx
mov ebx,[dword eax+SB16_sample_settings.DMA_length]
mov [dword DMA_length],ebx
mov eax,[dword eax+SB16_sample_settings.DMA_real_sr]
push eax
mov bl,[byte init_settings.IRQ_no]
lea edx,[SB16_virtualmixxer]
mov cx,cs
call setirqvector
cli
in al,21h
mov bl,1
mov cl,[byte init_settings.IRQ_no]
shl bl,cl
not bl
and al,bl
out 21h,al
mov al,01011000b
mov ah,[byte init_settings.DMA_no]
mov ebx,[dword DAC_PHYSICAL_PAGE]
mov ecx,[dword DMA_length]
lea ecx,[ecx*4]
dec ecx
call DMA_setup
mov al,41h
call SB_write_dac
pop eax
xchg al,ah
call SB_write_dac
mov al,ah
call SB_write_dac
mov al,0b6h
call SB_write_dac
mov al,030h
call SB_write_dac
mov eax,[dword DMA_length]
dec eax
call SB_write_dac
mov al,ah
call SB_write_dac
sti
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc SB16_deinit
cli
mov al,0d9h
call SB_write_dac
call sbsub1_deinit
sti
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; GUS DEPENDANT CODE ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;GUS CONST
GUS_irq_table db 0,0,1,2,0,3,0,4,0,0,0,5,6,0,0,7
GUS_dma_table db 0,1,0,2,0,3,4,5
;Gravis only
gus_base dd 0
gus_status dd 6
gus_timercontrol dd 8
gus_timerdata dd 9
gus_irqdmacontrol dd 0bh
gus_midictrl dd 100h
gus_mididata dd 101h
gus_voice dd 102h
gus_command dd 103h
gus_datalo dd 104h
gus_datahi dd 105h
gus_GF1_status dd 106h
gus_dram dd 107h
DMA_state db ?
gus_volume_table:
db 020h,040h,060h,080h,090h,094h,098h,09ch
db 0A0h,0A2h,0A4h,0A6h,0A8h,0AAh,0ACh,0AEh
db 0B0h,0B1h,0B2h,0B3h,0B4h,0B5h,0B6h,0B7h
db 0B8h,0B9h,0BAh,0BBh,0BCh,0BDh,0BEh,0BFh
db 0C0h,0C0h,0C1h,0C1h,0C2h,0C2h,0C3h,0C3h
db 0C4h,0C4h,0C5h,0C5h,0C6h,0C6h,0C7h,0C7h
db 0C8h,0C8h,0C9h,0C9h,0CAh,0CAh,0CBh,0CBh
db 0CCh,0CCh,0CDh,0CDh,0CEh,0CEh,0CFh,0CFh
db 0D0h,0D0h,0D0h,0D0h,0D1h,0D1h,0D1h,0D1h
db 0D2h,0D2h,0D2h,0D2h,0D3h,0D3h,0D3h,0D3h
db 0D4h,0D4h,0D4h,0D4h,0D5h,0D5h,0D5h,0D5h
db 0D6h,0D6h,0D6h,0D6h,0D7h,0D7h,0D7h,0D7h
db 0D8h,0D8h,0D8h,0D8h,0D9h,0D9h,0D9h,0D9h
db 0DAh,0DAh,0DAh,0DAh,0DBh,0DBh,0DBh,0DBh
db 0DCh,0DCh,0DCh,0DCh,0DDh,0DDh,0DDh,0DDh
db 0DEh,0DEh,0DEh,0DEh,0DFh,0DFh,0DFh,0DFh
db 0E0h,0E0h,0E0h,0E0h,0E0h,0E1h,0E1h,0E1h
db 0E1h,0E2h,0E2h,0E2h,0E2h,0E3h,0E3h,0E3h
db 0E3h,0E4h,0E4h,0E4h,0E4h,0E5h,0E5h,0E5h
db 0E5h,0E6h,0E6h,0E6h,0E6h,0E7h,0E7h,0E7h
db 0E7h,0E8h,0E8h,0E8h,0E8h,0E9h,0E9h,0E9h
db 0E9h,0EAh,0EAh,0EAh,0EAh,0EAh,0EBh,0EBh
db 0EBh,0EBh,0ECh,0ECh,0ECh,0ECh,0EDh,0EDh
db 0EDh,0EDh,0EEh,0EEh,0EEh,0EEh,0EFh,0EFh
db 0EFh,0EFh,0F0h,0F0h,0F0h,0F0h,0F1h,0F1h
db 0F1h,0F1h,0F2h,0F2h,0F2h,0F2h,0F3h,0F3h
db 0F3h,0F3h,0F4h,0F4h,0F4h,0F4h,0F4h,0F5h
db 0F5h,0F5h,0F5h,0F6h,0F6h,0F6h,0F6h,0F6h
db 0F7h,0F7h,0F7h,0F7h,0F8h,0F8h,0F8h,0F8h
db 0F9h,0F9h,0F9h,0F9h,0F9h,0F9h,0FAh,0FAh
db 0FAh,0FAh,0FBh,0FBh,0FBh,0FBh,0FBh,0FBh
db 0FBh,0FCh,0FCh,0FCh,0FCh,0FCh,0FCh,0FCh
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; GUS Code ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc GUSi_freq_convert
mov eax,[dword edi+tfunk_chan.rfreq]
xor edx,edx
mov ecx,43
div ecx
mov [dword edi+tfunk_chan.CARD_freq],eax
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc GUSi_volume_convert
xor eax,eax
cmp [byte edi+tfunk_chan.channel_kill],STOP
je @@transt
mov al,[byte funk_info.master_volume]
cmp al,0
je @@transt
xor ecx,ecx
mov cl,[byte edi+tfunk_chan.rvolume]
inc al
mul ecx
shr eax,4
@@transt:
mov al,[byte eax+gus_volume_table]
mov [byte edi+tfunk_chan.CARD_volume],al
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; GUS interface routines ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc GUS_set_freq
mov edx,[dword gus_command]
mov al,1
out dx,al
inc edx
mov eax,[dword edi+tfunk_chan.CARD_freq]
out dx,ax
ret
endp
; cl = volume to set
proc GUS_set_volume
cmp cl,[byte gus_volume_table]
jae @@cont
ret
@@cont:
mov edx,[dword gus_command]
MOV al,89h
OUT dx,al
INC edx
IN ax,dx
mov bl,ah
cmp bl,4
jae @@dont_level1
mov bl,4
@@dont_level1:
xor ch,ch
cmp bl,cl
je @@end
jb @@set_ramp_to_up
mov ch,040h
xchg bl,cl
@@set_ramp_to_up:
;bl = ramp start
;cl = ramp end
;ch = ramp direction
DEC edx
MOV al,0dh
OUT dx,al
ADD edx,2
MOV al,3
OUT dx,al
SUB edx,2
MOV al,7
OUT dx,al
ADD edx,2
MOV al,bl
OUT dx,al
SUB edx,2
MOV al,8
OUT dx,al
ADD edx,2
mov al,cl
OUT dx,al
SUB edx,2
MOV al,6
OUT dx,al
ADD edx,2
MOV al,3fh
OUT dx,al
sub edx,2
MOV al,0dh
OUT dx,al
ADD edx,2
MOV al,ch
OUT dx,al
@@loopramp:
sub edx,2
mov al,8dh
out dx,al
add edx,2
in al,dx
test al,1
jz @@loopramp
@@end:
ret
endp
proc GUS_load_channel
mov cl,[byte gus_volume_table]
call GUS_set_volume
mov edx,[dword gus_command]
xor al,al
out dx,al
add edx,2
mov al,3
out dx,al
mov eax,[funk_hr_ptr]
cmp [word eax+tfunk_hr.LZH_check_sum],"vF"
jne @@no_varbalance
sub edx,2
mov al,0ch
out dx,al
add edx,2
mov al,[byte edi+tfunk_chan.balance]
shr al,4
out dx,al
@@no_varbalance:
call GUS_set_freq
mov edx,[dword gus_command]
;Send sample begin
mov al,0ah
out dx,al
inc edx
mov eax,[dword edi+tfunk_chan.CARD_sample_ptr]
add eax,32
shr eax,7
out dx,ax
dec edx
mov al,0bh
out dx,al
inc edx
mov eax,[dword edi+tfunk_chan.CARD_sample_ptr]
add eax,32
shl eax,9
out dx,ax
dec edx
;Send sample start
mov al,2
out dx,al
inc edx
mov eax,[dword edi+tfunk_chan.start]
add eax,32
shr eax,7
out dx,ax
dec edx
mov al,3
out dx,al
inc edx
mov eax,[dword edi+tfunk_chan.start]
add eax,32
shl eax,9
out dx,ax
dec edx
;Send sample end
mov al,4
out dx,al
inc edx
mov eax,[dword edi+tfunk_chan.length]
sub eax,32
shr eax,7
out dx,ax
dec edx
mov al,5
out dx,al
inc edx
mov eax,[dword edi+tfunk_chan.length]
sub eax,32
shl eax,9
out dx,ax
mov cl,[byte edi+tfunk_chan.CARD_volume]
call GUS_set_volume
ret
endp
proc GUS_set_start
mov edx,[dword gus_command]
;Send sample start
mov al,2
out dx,al
inc edx
mov eax,[dword edi+tfunk_chan.start]
add eax,32
shr eax,7
out dx,ax
dec edx
mov al,3
out dx,al
inc edx
mov eax,[dword edi+tfunk_chan.start]
add eax,32
shl eax,9
out dx,ax
ret
endp
proc GUS_fire_channel
cmp [dword edi+tfunk_chan.length],64
jae @@cont
ret
@@cont:
mov edx,[dword gus_command]
xor al,al
out dx,al
test [byte edi+tfunk_chan.funkctrl],1b
jz @@dont_loop
mov al,8
@@dont_loop:
add edx,2
out dx,al
mov [byte edi+tfunk_chan.funkctrl],0
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc GUS_update
lea edi,[funk_chan1]
xor cl,cl
@@play_slot:
push ecx
mov al,cl
mov edx,[dword gus_voice]
out dx,al
test [byte edi+tfunk_chan.funkctrl],10b
jnz @@fire_channel
call GUS_set_freq
mov cl,[byte edi+tfunk_chan.CARD_volume]
call GUS_set_volume
test [byte edi+tfunk_chan.funkctrl],10000000b
jz @@done
and [byte edi+tfunk_chan.funkctrl],01111111b
call GUS_set_start
jmp @@done
@@fire_channel:
call GUS_load_channel
@@done:
pop ecx
add edi,size tfunk_chan
inc cl
cmp cl,8
jb @@play_slot
lea edi,[funk_chan1]
xor cl,cl
@@play_slot2:
mov al,cl
mov edx,[dword gus_voice]
out dx,al
test [byte edi+tfunk_chan.funkctrl],10b
jz @@done2
call GUS_fire_channel
@@done2:
add edi,size tfunk_chan
inc cl
cmp cl,8
jb @@play_slot2
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc GUS_mixxer
cld
push ds es
pushad
mov ax,DGROUP
mov ds,ax
mov es,ax
@@next_irq:
mov edx,[dword gus_status]
in al,dx
mov [byte @@irq_state],al
test [byte @@irq_state],10000000b
jnz @@DMA_interrupt
call funk_tracker
call GUS_update
mov edx,[dword gus_command]
mov al,45h
out dx,al
add edx,2
xor al,al
out dx,al
mov al,8
out dx,al
jmp @@end
@@DMA_interrupt:
mov edx,[dword gus_command]
mov al,041h
out dx,al
add edx,2
in al,dx
or [byte DMA_state],1
test [byte @@irq_state],11101111b
jz @@next_irq
@@end:
mov al,20h
out 20h,al
out 0a0h,al
popad
pop es ds
iretd
@@irq_state:
db ?
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc gus_delay
mov edx,[dword gus_dram]
in al,dx
in al,dx
in al,dx
in al,dx
in al,dx
in al,dx
in al,dx
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; esi ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc GUS_mem_in
mov edx,[dword gus_command]
mov al,43h
out dx,al
inc edx
mov eax,esi
out dx,ax
dec edx
mov al,44h
out dx,al
add edx,2
mov eax,esi
shr eax,16
out dx,al
add edx,2
in al,dx
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; edi ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc GUS_mem_out
push eax
mov edx,[dword gus_Command]
mov al,43h
out dx,al
inc edx
mov eax,edi
out dx,ax
dec edx
mov al,44h
out dx,al
add edx,2
mov eax,edi
shr eax,16
out dx,al
add edx,2
pop eax
out dx,al
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc GUS_find_mem
xor bl,bl
mov edi,100h
@@fm_loop:
mov al,0AAh
call GUS_mem_out
mov ecx,0FFFFh
@@bw_loop:
nop
dec ecx
jnz @@bw_loop
mov esi,edi
call GUS_mem_in
cmp al,0AAh
jnz @@exit
add edi,40000h
inc bl
cmp bl,4
jbe @@fm_loop
@@exit:
sub edi,100h
jz @@standard
mov [dword funk_info.sample_memory_lim],edi
ret
@@standard:
mov [dword funk_info.sample_memory_lim],40000h
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; NB/this 'total reset' routine is from adam's dos32 routines ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc GUS_total_reset
cmp [byte init_settings.IRQ_no],0
je @@zero_irq1
movzx edx,[byte init_settings.IRQ_no]
mov dl,[byte edx+GUS_irq_table]
or dl,dl
jz @@invalid_setting
@@Zero_irq1:
mov [byte @@irq_control],dl
movzx edx,[byte init_settings.IRQ_no2]
or dl,dl
jz @@Zero_irq2
mov dl,[byte edx+GUS_irq_table]
or dl,dl
jz @@invalid_setting
shl dl,3
@@Zero_irq2:
or [byte @@irq_control],dl
mov al,[byte init_settings.IRQ_no]
cmp al,[byte init_settings.IRQ_no2]
jne @@diff_irqs
cmp [byte init_settings.IRQ_no],0
je @@diff_irqs
and [byte @@irq_control],0111b
or [byte @@irq_control],40h
@@diff_irqs:
movzx edx,[byte init_settings.DMA_no]
or dl,dl
jz @@Zero_dma2
mov dl,[byte edx+GUS_dma_table]
or dl,dl
jz @@invalid_setting
@@Zero_dma1:
mov [byte @@dma_control],dl
movzx edx,[byte init_settings.DMA_no2]
or dl,dl
jz @@Zero_dma2
mov dl,[byte edx+GUS_dma_table]
or dl,dl
jz @@invalid_setting
shl dl,3
@@Zero_dma2:
or [byte @@dma_control],dl
mov al,[byte init_settings.DMA_no]
cmp al,[byte init_settings.DMA_no2]
jne @@diff_dmas
and cl,cl
jz @@diff_irqs
and [byte @@dma_control],0111b
or [byte @@dma_control],40h
@@diff_dmas:
cli
mov ecx,200h
loop $
mov edx,[dword GUS_base]
add edx,0fh
mov al,5
out dx,al
mov edx,[dword GUS_base]
mov al,00001011b
out dx,al
mov edx,[dword GUS_irqdmacontrol]
xor al,al
out dx,al
mov edx,[dword GUS_base]
add edx,0fh
xor al,al
out dx,al
mov edx,[dword GUS_base]
mov al,00001011b
out dx,al
mov edx,[dword GUS_irqdmacontrol]
mov al,[byte @@dma_control]
or al,80h
out dx,al
mov edx,[dword GUS_base]
mov al,01001011b
out dx,al
mov edx,[dword gus_irqdmacontrol]
mov al,[byte @@irq_control]
out dx,al
mov edx,[dword GUS_base]
mov al,00001011b
out dx,al
mov edx,[dword gus_irqdmacontrol]
mov al,[byte @@dma_control]
out dx,al
mov edx,[dword GUS_base]
mov al,01001011b
out dx,al
mov edx,[dword gus_irqdmacontrol]
mov al,[byte @@irq_control]
out dx,al
mov edx,[dword gus_voice]
xor al,al
out dx,al
mov edx,[dword GUS_base]
mov al,0001001b
out dx,al
mov edx,[dword gus_voice]
xor al,al
out dx,al
in al,0A1h
mov ah,al
in al,21h
mov cl,[byte init_settings.IRQ_no]
cmp cl,2
jne @@j3
mov cl,9
@@j3:
mov ebx,1
shl ebx,cl
not ebx
and eax,ebx
mov cl,[byte init_settings.IRQ_no2]
cmp cl,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
;part II
mov edx,[dword gus_command]
mov al,04Ch
out dx,al
add edx,2
mov al,00000000b
out dx,al
mov ecx,10
@@J56:
call gus_delay
loop @@J56
mov edx,[dword gus_command]
mov al,04Ch
out dx,al
add edx,2
mov al,00000001b
out dx,al
mov ecx,10
@@J57:
call gus_delay
loop @@J57
mov edx,[dword gus_midictrl]
mov al,00000011b
out dx,al
mov ecx,10
@@J58:
call gus_delay
loop @@J58
xor al,al
out dx,al
mov edx,[dword gus_command]
mov al,041h
out dx,al
add edx,2
xor al,al
out dx,al
mov edx,[dword gus_command]
mov al,045h
out dx,al
add edx,2
xor al,al
out dx,al
mov edx,[dword gus_command]
mov al,049h
out dx,al
add edx,2
xor al,al
out dx,al
mov edx,[dword gus_command]
mov al,049h
out dx,al
add edx,2
xor al,al
out dx,al
mov edx,[dword gus_command]
mov al,0eh
out dx,al
add edx,2
mov al,13 or 0C0h
out dx,al
mov edx,[dword gus_GF1_status]
in al,dx
mov edx,[dword gus_command]
mov al,041h
out dx,al
add edx,2
in al,dx
mov edx,[dword gus_command]
mov al,049h
out dx,al
add edx,2
in al,dx
@@ClrFIFO:
mov edx,[dword gus_command]
mov al,08fh
out dx,al
add edx,2
in al,dx
and al,11000000b
cmp al,11000000b
jne @@ClrFIFO
xor bl,bl
@@stop_loop:
mov edx,[dword GUS_voice]
mov al,bl
out dx,al
mov edx,[dword gus_command]
xor al,al
out dx,al
add edx,2
xor al,al
out dx,al
mov edx,[dword gus_command]
xor al,al
out dx,al
add edx,2
mov al,10b
out dx,al
mov edx,[dword gus_command]
mov al,0dh
out dx,al
add edx,2
mov al,10b
out dx,al
mov edx,[dword gus_command]
mov al,09h
out dx,al
inc edx
movzx eax,[byte gus_volume_table]
shl eax,8
out dx,ax
call gus_delay
inc bl
cmp bl,14
jb @@stop_loop
mov edx,[dword gus_GF1_status]
in al,dx
mov edx,[dword gus_command]
mov al,041h
out dx,al
add edx,2
in al,dx
mov edx,[dword gus_command]
mov al,049h
out dx,al
add edx,2
in al,dx
@@Clr2FIFO:
mov edx,[dword gus_command]
mov al,08fh
out dx,al
add edx,2
in al,dx
and al,11000000b
cmp al,11000000b
jne @@Clr2FIFO
mov edx,[dword gus_command]
mov al,0eh
out dx,al
add edx,2
mov al,13 or 0C0h
out dx,al
mov edx,[dword gus_command]
mov al,04ch
out dx,al
add edx,2
mov al,00000111b
out dx,al
sti
@@invalid_setting:
ret
@@dma_control:
db ?
@@irq_control:
db ?
@@gf1:
db ?
@@midi:
db ?
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc GUS_reset
;added code
mov edx,[dword gus_base]
mov al,0bh
out dx,al
;added code
mov ebx,[dword gus_Command]
mov ecx,[dword gus_DataHi]
mov edx,ebx
mov al,4Ch
out dx,al
mov edx,ecx
xor al,al
out dx,al
call gus_delay
call gus_delay
mov edx,ebx
mov al,4Ch
out dx,al
mov edx,ecx
mov al,1
out dx,al
call gus_delay
call gus_delay
mov edx,ebx
mov al,41h
out dx,al
mov edx,ecx
xor al,al
out dx,al
mov edx,ebx
mov al,45h
out dx,al
mov edx,ecx
xor al,al
out dx,al
mov edx,ebx
mov al,49h
out dx,al
mov edx,ecx
xor al,al
out dx,al
mov edx,ebx
mov al,0Eh
out dx,al
add edx,2
mov al,13
or al,0Ch
out dx,al
mov edx,[dword gus_Status]
in al,dx
mov edx,ebx
mov al,41h
out dx,al
mov edx,ecx
in al,dx
mov edx,ebx
mov al,49h
out dx,al
mov edx,ecx
in al,dx
mov edx,ebx
mov al,8Fh
out dx,al
mov edx,ecx
in al,dx
push ebx ecx
xor ecx,ecx
mov bl,0
@@VoiceClearLoop:
mov edx,[dword gus_Voice]
mov al,cl
out dx,al
inc edx
xor al,al
out dx,al
add edx,2
mov al,3
out dx,al
sub edx,2
mov al,0Dh
out dx,al
add edx,2
mov al,3
out dx,al
sub edx,2
mov al,0ch
out dx,al
add edx,2
mov al,bl
out dx,al
sub edx,2
mov al,09h
out dx,al
inc edx
movzx eax,[byte gus_volume_table]
shl eax,8
out dx,ax
xor bl,0ffh
inc ecx
cmp ecx,13
jnz @@VoiceClearLoop
pop ecx ebx
mov edx,ebx
mov al,41h
out dx,al
mov edx,ecx
in al,dx
mov edx,ebx
mov al,49h
out dx,al
mov edx,ecx
in al,dx
mov edx,ebx
mov al,8Fh
out dx,al
mov edx,ecx
in al,dx
mov edx,ebx
mov al,4Ch
out dx,al
mov edx,ecx
mov al,7
out dx,al
;added code
mov edx,ebx
mov al,4Ch
out dx,al
mov edx,ecx
mov al,7
out dx,al
;;;;
mov edx,[dword gus_base] ;set irq
mov al,4bh
out dx,al
movzx eax,[byte init_settings.IRQ_no]
mov al,[byte eax+GUS_irq_table]
push eax
MOV edx,[dword gus_irqdmacontrol]
OUT dx,AL
;;;;
mov edx,[dword gus_base] ;set dma
mov al,0bh
out dx,al
movzx eax,[byte init_settings.DMA_no]
mov al,[byte eax+GUS_dma_table]
MOV edx,[dword gus_irqdmacontrol]
OUT dx,AL
;;;;
mov edx,[dword gus_base] ;set irq
mov al,4bh
out dx,al
MOV edx,[dword gus_irqdmacontrol]
pop eax
OUT dx,AL
;;;;
mov edx,[dword gus_base]
mov al,0bh
out dx,al
mov edx,ebx
mov al,41h
out dx,al
mov edx,ecx
xor al,al
out dx,al
mov edx,ebx
mov al,45h
out dx,al
mov edx,ecx
xor al,al
out dx,al
mov edx,ebx
mov al,49h
out dx,al
mov edx,ecx
xor al,al
out dx,al
MOV AL,80h
MOV edx,[dword gus_timerdata]
OUT dx,AL
xor al,al
MOV edx,[dword gus_timerdata]
OUT dx,AL
mov edx,[dword gus_base]
mov al,0bh
out dx,al
;added code
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; GUS Interrupt ready ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc GUS_intready
cli
xor cl,cl
xor bl,bl
@@resetb:
mov edx,[dword gus_Voice]
mov al,cl
out dx,al
mov edx,[dword gus_command]
mov al,0ch
out dx,al
add edx,2
mov al,bl
out dx,al
xor bl,0ffh
inc cl
cmp cl,13
jnz @@resetb
mov edx,[dword gus_command]
mov al,45h
out dx,al
mov al,2bh
and al,0f7h
mov edx,[dword gus_datahi]
out dx,al
xor al,al
out 021h,al
xor al,al
out 0a1h,al
mov al,20h
out 020h,al
mov al,20h
out 0a0h,al
mov al,47h
mov edx,[dword gus_command]
out dx,al
mov al,193 ;<<-speed
add edx,2
out dx,al
sub edx,2
mov al,45h
out dx,al
add edx,2
mov al,8
out dx,al
mov edx,[dword gus_timercontrol]
mov al,4
out dx,al
mov edx,[dword gus_timerdata]
mov al,2
out dx,al
mov al,8
mov edx,[dword gus_base]
out dx,al
sti
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; GUS Save INT timer registers ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc GUS_init
mov bl,[byte init_settings.IRQ_no]
call getirqvector
mov [dword DAC_old_irq_ofs],edx
mov [word DAC_old_irq_sel],cx
mov bl,[byte init_settings.IRQ_no]
lea edx,[GUS_mixxer]
mov ecx,cs
call setirqvector
call GUS_total_reset
call GUS_reset
call GUS_intready
ret
endp
proc GUS_deinit
call GUS_reset
mov bl,[byte init_settings.IRQ_no]
mov edx,[dword DAC_old_irq_ofs]
mov cx,[word DAC_old_irq_sel]
call setirqvector
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; esi trans mem ;
; edi gus mem locatin ;
; ecx bytes to trans ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc gus_upload
cli
mov edx,[dword gus_Command]
@@MainLoop:
mov edx,[dword gus_Command]
mov al,44h
out dx,al
add edx,2
mov eax,edi
shr eax,16
out dx,al
mov edx,[dword gus_Command]
mov al,43h
out dx,al
inc edx
mov eax,edi
out dx,ax
mov edx,[dword gus_dram]
outsb
inc edi
dec ecx
jnz @@MainLoop
sti
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; edi trans mem ;
; esi gus mem locatin ;
; ecx bytes to trans ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc gus_dnload
cli
mov edx,[dword gus_Command]
@@MainLoop:
mov edx,[dword gus_Command]
mov al,44h
out dx,al
add edx,2
mov eax,esi
shr eax,16
out dx,al
mov edx,[dword gus_Command]
mov al,43h
out dx,al
inc edx
mov eax,esi
out dx,ax
mov edx,[dword gus_dram]
insb
inc esi
dec ecx
jnz @@MainLoop
sti
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; PAS DEPENDANT CODE ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc PAS16_virtualmixxer
cld
push ds es
pushad
mov ax,DGROUP
mov ds,ax
mov es,ax
@@ISR_l:
mov edx,INTRCTLRST ;clear the interrupt
xor edx,[_MVTranslateCode] ;xlate the board address
in al,dx
test al,bISsampbuff+bISsamprate ;our interrupt?
jz @@exit_int
out dx,al ;yes, flush it...
mov esi,[dword DAC_mix_buffer]
mov edx,[dword DAC_mix_buffer_right]
mov edi,[dword DAC_mix_buffer2]
add edi,[DAC_double_buf1]
mov eax,[DAC_double_buf1]
xchg eax,[DAC_double_buf2]
mov [DAC_double_buf1],eax
mov ecx,[dword DAC_mix_buffer_size]
xor ebx,ebx
@@trans16:
mov eax,[edx+ebx]
shl eax,16
mov ax,[word esi+ebx]
mov [edi+ebx*2],eax
add ebx,2
dec ecx
jnz @@trans16
call funk_tracker
mov ecx,[dword DAC_mix_buffer_size]
shr ecx,1
mov edi,[dword DAC_mix_buffer]
xor eax,eax
rep stosd
mov ecx,[dword DAC_mix_buffer_size]
shr ecx,1
mov edi,[dword DAC_mix_buffer_right]
rep stosd
lea ebx,[funk_chan1]
mov edi,[dword DAC_mix_buffer]
call DAC_channel_mixxer
lea ebx,[funk_chan2]
mov edi,[dword DAC_mix_buffer_right]
call DAC_channel_mixxer
lea ebx,[funk_chan3]
mov edi,[dword DAC_mix_buffer]
call DAC_channel_mixxer
lea ebx,[funk_chan4]
mov edi,[dword DAC_mix_buffer_right]
call DAC_channel_mixxer
lea ebx,[funk_chan5]
mov edi,[dword DAC_mix_buffer]
call DAC_channel_mixxer
lea ebx,[funk_chan6]
mov edi,[dword DAC_mix_buffer_right]
call DAC_channel_mixxer
lea ebx,[funk_chan7]
mov edi,[dword DAC_mix_buffer]
call DAC_channel_mixxer
lea ebx,[funk_chan8]
mov edi,[dword DAC_mix_buffer_right]
call DAC_channel_mixxer
jmp @@ISR_l
@@exit_int:
mov al,20h ;clear the interrupt
cmp [init_settings.IRQ_no],8 ;2nd IRQ controller?
jb @@F1
out 0A0h,al
@@F1:
out 020h,al
popad
pop es ds
iretd
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; Pro Audio routines for FunkTracker ;
; ;
; Routines from Media Vision SDK, Inc. ;
; Copyright (c) 1991,1992. All Rights Res. ;
; ;
; Converted to P-mode by Jason Nunn ;
; ;
; This INIT code that talks to MVSOUND.SYS isn't supposed to run in P-mode;
; So, problems _may_ occur. I'll replace it when i get time. ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Hardware associated with the PAS1/PAS2/CDPC
DEFAULT_BASE = 00388h ;default base I/O address
ALT_BASE_1 = 00384h ;first alternate address
ALT_BASE_2 = 0038Ch ;second alternate address
ALT_BASE_3 = 00288h ;third alternate address
USE_ACTIVE_ADDR = 00000h ;uses what is currently active
AUDIOFILT = 00B8Ah ;Audio Filter Control Register
INTRCTLRST = 00B89h ;Interrupt Control Status Register
INTRCTLR = 00B8Bh ;Interrupt Control Register write
CROSSCHANNEL = 00F8Ah ;Cross Channel Register
SAMPLERATE = 01388h ;(t0) Sample Rate Timer Register
SAMPLECNT = 01389h ;(t1) Sample Count Register
TMRCTLR = 0138Bh ;Local Timer Control Register
; Factory Default Settings
DEFAULTDMA = 1 ;DMA channel 1
DEFAULTIRQ = 7 ;IRQ channel 7
DEFAULTINT = 65h ;Interrupt # for software interface
; mixer select
OUTPUTMIXER = 00h ;output mixer H/W select
INPUTMIXER = 40h ;input mixer select
DEFMIXER = -1 ;use last mixer selected
MIXERMAX = 1fh ;maximum mixer setting
MVVOLUMEMAX = 3fh ;MVA508 maximum mixer setting
NSVOLUMEMAX = 28h ;National maximum mixer setting
EQUALIZERMAX = 0ch ;maximum equalizer setting
EQUALIZERMID = 06h ;maximum mid setting
; Filter register bits
fFIdatabits = 00011111B ;filter select and decode field bits
fFImutebits = 00100000B ;filter mute field bits
fFIpcmbits = 11000000B ;filter sample rate field bits
bFImute = 00100000B ;filter mute bit
bFIsrate = 01000000B ;filter sample rate timer mask
bFIsbuff = 10000000B ;filter sample buffer counter mask
FILTERMAX = 6 ;six possible settings
; Cross Channel Bit definitions
fCCcrossbits = 00001111B ;; cross channel bit field
fCCpcmbits = 11110000B ;; pcm/dma control bit field
bCCr2r = 00000001B ;; CROSSCHANNEL Right to Right
bCCl2r = 00000010B ;; CROSSCHANNEL Left to Right
bCCr2l = 00000100B ;; CROSSCHANNEL Right to Right
bCCl2l = 00001000B ;; CROSSCHANNEL Left to Left
bCCdac = 00010000B ;; DAC/ADC Control
bCCmono = 00100000B ;; PCM Monaural Enable
bCCenapcm = 01000000B ;; Enable PCM state machine
bCCdrq = 10000000B ;; Enable DRQ bit
; Interrupt Control Register Bits
fICintmaskbits = 00011111B ;; interrupt mask field bits
fICrevbits = 11100000B ;; revision mask field bits
bICsamprate = 00000100B ;; Sample Rate timer interrupt enable
bICsampbuff = 00001000B ;; Sample buffer timer interrupt enable
fICrevshr = 5 ;; rotate rev bits to lsb
;Interrupt Status Register Bits
fISints = 1fh ; Interrupt bit field
bISleftfm = 01h ; Left FM interrupt active
bISritfm = 02h ; Right FM interrupt active
bISsamprate = 04h ; Sample Rate timer interrupt active
bISsampbuff = 08h ; Sample buffer timer interrupt active
bISmidi = 10h ; MIDI interrupt active
bISPCMlr = 20h ; PCM left/right active
bISActive = 40h ; Hardware is active (not in reset)
bISClip = 80h ; Sample Clipping has occured
MASTERCHIPR = 0ff88h ;; Master Chip Rev (r)
ENHANCEDSCSI = 07f89h ;; Enhanced SCSI detect port
SYSCONFIG2 = 08389h ;; System Config 2 (r/w)
COMPATREGE = 0f788h ;; Compatible Rgister Enable (r/w)
MASTERMODRD = 0ff8bh ;; Master Mode Read (r)
SLAVEMODRD = 0ef8bh ;; Slave Mode Read (r)
; Sys Config 2
bSC216bit = 00000100b ;; 16 bit audio
bSC212bit = 00001000b ;; 12 bit interleaving (d2 must be set too)
; I/O Config 3
bIC3pcmint = 00001111b ;; pcm IRQ channel select
bIC3cdint = 11110000b ;; cd IRQ channel select
; Compatibility Register
cpMPUEmulation = 00000001b ;; MPU emuation is on bit
; Slave Mode Read
bSMRDdrvtyp = 00000011b ;; drive interface type
bSMRDfmtyp = 00000100b ;; FM chip type
bSMRDdactyp = 00001000b ;; 16 bit dac (1) or 8 bit dac (0)
; Master Mode Read
bMMRDatps2 = 00000001b ;; AT(1) or PS2(0) bus
bMMRDmsmd = 00000100b ;; master/slave mode
; Interrupt Controller #1 Port Addresses and Interrupt Masks
IRQ1MASKREG = 021h ;; 8259 mask register
INT7MSK = 10000000B ;; interrupt 7 mask
; Interrupt Controller #2 Port Addresses and Interrupt Masks
IRQ2MASKREG = 0A1h ;; 8259 mask register
;; dma controller #1 port addresses
DMAC0ADDR = 000h ;; DMA channel 0 Base & Current Address
DMAC0COUNT = 001h ;; DMA channel 0 Base & Current Count
DMAC1ADDR = 002h ;; DMA channel 1 Base & Current Address
DMAC1COUNT = 003h ;; DMA channel 1 Base & Current Count
DMAC2ADDR = 004h ;; DMA channel 2 Base & Current Address
DMAC2COUNT = 005h ;; DMA channel 2 Base & Current Count
DMAC3ADDR = 006h ;; DMA channel 3 Base & Current Address
DMAC3COUNT = 007h ;; DMA channel 3 Base & Current Count
DMA2C4ADDR = 0C0h ;; DMA channel 4 Base & Current Address
DMA2C4COUNT = 0C2h ;; DMA channel 4 Base & Current Count
DMA2C5ADDR = 0C4h ;; DMA channel 5 Base & Current Address
DMA2C5COUNT = 0C6h ;; DMA channel 5 Base & Current Count
DMA2C6ADDR = 0C8h ;; DMA channel 6 Base & Current Address
DMA2C6COUNT = 0CAh ;; DMA channel 6 Base & Current Count
DMA2C7ADDR = 0CCh ;; DMA channel 7 Base & Current Address
DMA2C7COUNT = 0CEh ;; DMA channel 7 Base & Current Count
DMARDSTAT = 008h ;; DMA read status
DMAWRCNTRL = 008h ;; DMA write command register
DMAWREQ = 009h ;; DMA write request register
DMAWRSMR = 00Ah ;; DMA write single mask register
DMAWRMODE = 00Bh ;; DMA write mode register
DMACLEAR = 00Ch ;; DMA clear low/high flip-flop
DMARDTEMP = 00Dh ;; DMA read temp register
DMAWRCLR = 00Dh ;; DMA write master clear
DMACLRMSK = 00Eh ;; DMA clear mask register
DMAWRALL = 00Fh ;; DMA write all mask register bits
DMA2RDSTAT = 0D0h ;; DMA read status
DMA2WRCNTRL = 0D0h ;; DMA write command register
DMA2WREQ = 0D2h ;; DMA write r=est register
DMA2WRSMR = 0D4h ;; DMA write single mask register
DMA2WRMODE = 0D6h ;; DMA write mode register
DMA2CLEAR = 0D8h ;; DMA clear low/high flip-flop
DMA2RDTEMP = 0DAh ;; DMA read temp register
DMA2WRCLR = 0DAh ;; DMA write master clear
DMA2CLRMSK = 0DCh ;; DMA clear mask register
DMA2WRALL = 0DEh ;; DMA write all mask register bits
CH0PAGEREG = 087h ;; Channel 0 Page Register
CH1PAGEREG = 083h ;; Channel 1 Page Register
CH2PAGEREG = 081h ;; Channel 2 Page Register
CH3PAGEREG = 082h ;; Channel 3 Page Register
CH5PAGEREG = 08Bh ;; Channel 5 Page Register
CH6PAGEREG = 089h ;; Channel 6 Page Register
CH7PAGEREG = 08Ah ;; Channel 7 Page Register
struc MVState
_sysspkrtmr db 0 ; 42 System Speaker Timer Address
_systmrctlr db 0 ; 43 System Timer Control
_sysspkrreg db 0 ; 61 System Speaker Register
_joystick db 0 ; 201 Joystick Register
_lfmaddr db 0 ; 388 Left FM Synth Address
_lfmdata db 0 ; 389 Left FM Synth Data
_rfmaddr db 0 ; 38A Right FM Synth Address
_rfmdata db 0 ; 38B Right FM Synth Data
_dfmaddr db 0 ; 788 Dual FM Synthesizer Address Register
_dfmdata db 0 ; 789 Dual FM Synthesizer Data Register
db 0 ; reserved for future use
_paudiomixr db 0 ; 78B Paralllel Audio Mixer Control
_audiomixr db 0 ; B88 Audio Mixer Control
_intrctlrst db 0 ; B89 Interrupt Status
_audiofilt db 0 ; B8A Audio Filter Control
_intrctlr db 0 ; B8B Interrupt Control
_pcmdata db 0 ; F88 PCM Data I/O Register
_RESRVD2 db 0 ; reserved
_crosschannel db 0 ; F8A Cross Channel
_RESRVD3 db 0 ; reserved
_samplerate dw 0 ; 1388 Sample Rate Timer
_samplecnt dw 0 ; 1389 Sample Count Register
_spkrtmr dw 0 ; 138A Shadow Speaker Timer Count
_tmrctlr db 0 ; 138B Shadow Speaker Timer Control
_mdirqvect db 0 ; 1788 MIDI IRQ Vector Register
_mdsysctlr db 0 ; 1789 MIDI System Control Register
_mdsysstat db 0 ; 178A MIDI IRQ Status Register
_mdirqclr db 0 ; 178B MIDI IRQ Clear Register
_mdgroup1 db 0 ; 1B88 MIDI Group #1 Register
_mdgroup2 db 0 ; 1B89 MIDI Group #2 Register
_mdgroup3 db 0 ; 1B8A MIDI Group #3 Register
_mdgroup4 db 0 ; 1B8B MIDI Group #4 Register
ends
bMVA508 = 0000000000000001b ; MVA508(1) or National(0)
bMVPS2 = 0000000000000010b ; PS2 bus stuff
bMVSLAVE = 0000000000000100b ; CDPC Slave device is present
bMVSCSI = 0000000000001000b ; SCSI interface
bMVENHSCSI = 0000000000010000b ; Enhanced SCSI interface
bMVSONY = 0000000000100000b ; Sony 535 interface
bMVDAC16 = 0000000001000000b ; 16 bit DAC
bMVSBEMUL = 0000000010000000b ; SB h/w emulation
bMVMPUEMUL = 0000000100000000b ; MPU h/w emulation
bMVOPL3 = 0000001000000000b ; OPL3(1) or 3812(0)
bMV101 = 0000010000000000b ; MV101 ASIC
bMV101_REV = 0111100000000000b ; MV101 Revision
bMV101_MORE = 1000000000000000b ; more bits in BX
;; Define the ASIC versions
ASIC_VERSION_B = 0000000000000010b ; revision B
ASIC_VERSION_C = 0000000000000011b ; revision C
ASIC_VERSION_D = 0000000000000100b ; revision D
ASIC_VERSION_E = 0000000000000101b ; revision E
ASIC_VERSION_F = 0000000000000110b ; revision F
;; First Pro Audio Spectrum feature list
PRODUCT_PROAUDIO = bMVSCSI
;; Pro Audio Plus feature list
PRODUCT_PROPLUS = bMV101+bMVSCSI+bMVENHSCSI+bMVSBEMUL+bMVOPL3
;; Pro Audio Spectrum 16 feature list
PRODUCT_PRO16 = bMV101+bMVA508+bMVSCSI+bMVENHSCSI+bMVSBEMUL+bMVDAC16+bMVOPL3
;; CDPC feature list
PRODUCT_CDPC = bMV101+bMVSLAVE+bMVSONY+bMVSBEMUL+bMVDAC16+bMVOPL3
;; Set each one to zero - to be init later if selected
PROAS100 = 0
PROAS200 = 0
PROAS300 = 0
CDPC = 0
PRODUCTDEFINED = 0 ; to be set if a product is selected
_MVTranslateCode dd 0 ; I/O base xor default_base
_MVHWVersionBits dw -1 ; holds the product feature bits
VERSION_PAS = 0 ; Pro Audio Spectrum
VERSION_PASPLUS = 1 ; Pro Audio Plus card
VERSION_PAS16 = 2 ; Pro Audio 16 card
VERSION_CDPC = 3 ; CDPC card & unit
; The following equates build up a mask of bits that we do wish to keep
; when comparing feature bits. The zero bits can be ignored, whereas, the
; the 1 bits must match.
PASdocare = bMVA508 OR bMVDAC16 OR bMVOPL3 OR bMV101
PASPLUSdocare = bMVA508 OR bMVDAC16 OR bMVOPL3 OR bMV101
PAS16docare = bMVA508 OR bMVDAC16 OR bMVOPL3 OR bMV101
CDPCdocare = bMVA508 OR bMVDAC16 OR bMVOPL3 OR bMV101
label MVProductIDTable
dw PRODUCT_PROAUDIO and PASdocare
dw PRODUCT_PROPLUS and PASPLUSdocare
dw PRODUCT_PRO16 and PAS16docare
dw PRODUCT_CDPC and CDPCdocare
dw -1
label MVDoCareBits
dw PASdocare
dw PASPLUSdocare
dw PAS16docare
dw CDPCdocare
dw -1
struc dmaaddr
_dmach db ? ; DMA channel selected
_dmardstat db ? ; DMA read status
_dmawrcntrl db ? ; DMA write command register
_dmawreq db ? ; DMA write request register
_dmawrsmr db ? ; DMA write single mask register
_dmawrmode db ? ; DMA write mode register
_dmaclear db ? ; DMA clear low/high flip-flop
_dmardtemp db ? ; DMA read temp register
_dmawrclr db ? ; DMA write master clear
_dmaclrmsk db ? ; DMA clear mask register
_dmawrall db ? ; DMA write all mask register bits
ends
MVOurDMAPageReg dw CH1PAGEREG ; default to DMA channel 1 page reg
MVOurDMAddress dw DMAC1ADDR ; default to DMA channel 1 address reg
label DMA1AddrTable
db DEFAULTDMA ; DMA channel selected
db DMARDSTAT ; DMA read status
db DMAWRCNTRL ; DMA write command register
db DMAWREQ ; DMA write request register
db DMAWRSMR ; DMA write single mask register
db DMAWRMODE ; DMA write mode register
db DMACLEAR ; DMA clear low/high flip-flop
db DMARDTEMP ; DMA read temp register
db DMAWRCLR ; DMA write master clear
db DMACLRMSK ; DMA clear mask register
db DMAWRALL ; DMA write all mask register bits
; table of address pointers to the various DMA 2 addresses
label DMA2AddrTable
db DEFAULTDMA ; DMA channel selected
db DMA2RDSTAT ; DMA read status
db DMA2WRCNTRL; DMA write command register
db DMA2WREQ ; DMA write request register
db DMA2WRSMR ; DMA write single mask register
db DMA2WRMODE ; DMA write mode register
db DMA2CLEAR ; DMA clear low/high flip-flop
db DMA2RDTEMP ; DMA read temp register
db DMA2WRCLR ; DMA write master clear
db DMA2CLRMSK ; DMA clear mask register
db DMA2WRALL ; DMA write all mask register bits
PCM_DMAPointer dd offset DMA1AddrTable ;default to channel 1 table
MVTheIRQMask db INT7MSK ;8259 interrupt mask
MVSampleSize db 2 ;sample size: 0=8,1=12,2=16
mvhwShadowPointer dd 0 ;points to the start of the data table
MVHardwareShadowTable MVState <>
MVTypeOfSetup db 0 ;polled/dma interrupt masks & stuff..
mvStatusWord dw 0 ;Holds current status:
; 0 = inactive, available
; 1 = currently playing
; 2 = currently recording
DMAMASK = bICsampbuff ;dma mask
POLLEDMASK = bICsamprate+bICsampbuff ;polled mask
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc PCM_pause
jmp @@j
@@j:
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; Given a specific I/O address, this routine will see if the ;
; hardware exists at this address. ;
; ;
; Entry Conditions: ;
; DI holds the I/O address to test ;
; BX:CX = bMVSCSI ;
; ;
; Exit Conditions: ;
; BX:CX = the bit fields that identify the board ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc SearchHWVersion
; calculate the translation code
xor edi,DEFAULT_BASE
mov eax,0BC00H ;make sure MVSOUND.SYS is loaded
mov ebx,'??' ;this is our way of knowing if the
xor ecx,ecx ;hardware is actually present.
xor edx,edx
int 2fh ;get the ID pattern
xor bx,cx ;build the result
xor bx,dx
cmp bx,'MV' ;if not here, exit...
jnz @@sehw_bad
; get the MVSOUND.SYS specified DMA and IRQ channel
mov eax,0bc04h ;get the DMA and IRQ numbers
int 2fh
mov [init_settings.DMA_no],bl ;save the correct DMA & IRQ
mov [init_settings.IRQ_no],cl
; grab the version # in the interrupt mask. The top few bits hold the version #
mov edx,INTRCTLR ;board ID is in MSB 3 bits
xor edx,edi
in al,dx
cmp al,-1 ;bus float meaning not present?
je @@sehw_bad ;yes, there is no card here
mov ah,al
xor al,fICrevbits
out dx,al
call PCM_pause
call PCM_pause
in al,dx
cmp al,ah
xchg al,ah
out dx,al
jnz @@sehw_bad ;we have a bogus board
and ax,fICrevbits ;isolate the ID bits & clear AH
mov cl,fICrevshr ;shift the bits into a meaningful
shr al,cl ;position (least signficant bits)
movzx esi,ax ;save the version #
; We do have hardware! Load the product bit definitions
sub ebx,ebx
mov ecx,bMVSCSI ;setup bx:cx for the original PAS
or al,al ;is this the first version of h/w?
jz @@sehw_done ;yes, simple exit will do.
; Checks the installed hardware for all the feature bits. ;
; All second generation Pro Audio cards use the MV101 and have SB emulation.
or ecx,bMVSBEMUL+bMV101 ;force SB emulation
; determine if the enhanced SCSI interface is present
mov edx,ENHANCEDSCSI ;test for SCSI mod (U48)
xor edx,edi ;modify via the translate code
out dx,al ;strobe
call PCM_pause ;I/O bus delay
in al,dx ;get the bit
and al,1 ; bit0==1 means old SCSI PAL
cmp al,1 ;reverse sense
sbb eax,eax ;ax = ffff if enhanced SCSI
and eax,bMVENHSCSI
or ecx,eax
; determine AT/PS2, CDPC slave mode
mov edx,MASTERMODRD
xor edx,edi
in al,dx
test al,bMMRDatps2 ;AT(1) or PS2(0)
jnz @@F1
or ecx,bMVPS2
@@F1:
test al,bMMRDmsmd ;Master(0) or Slave(1)
jz @@F2
or ecx,bMVSLAVE
@@f2:
push ecx
mov edx,MASTERCHIPR
xor edx,edi
in al,dx
and ax,000Fh
mov cl,11
shl eax,cl
pop ecx
or ecx,eax
; determine the CDROM drive type, FM chip, 8/16 bit DAC, and mixer
mov edx,SLAVEMODRD
xor edx,edi
in al,dx
test al,bSMRDdactyp ;16 bit DAC?
jz @@F3 ;no, its an 8 bit DAC
or ecx,bMVDAC16 ;its a 16 bit DAC
@@f3:
test al,bSMRDfmtyp ;OPL3 chip?
jz @@F4 ;no, so it's the PAS16 card
or ecx,bMVOPL3 ;is an OPL3
@@f4:
mov edx,ecx ;inference check for new mixer
and edx,bMVSLAVE+bMVDAC16 ;Slave & 16 bit dac is the CDPC
cmp edx,bMVDAC16 ;16 bit DAC on master?
jnz @@F5 ;no, it's the CDPC with Nation mixer
or ecx,bMVA508
@@f5:
and al,bSMRDdrvtyp ;isolate the CDROM drive type
cmp al,2 ;Sony 535 interface?
jnz @@F6 ;no, continue on...
and ecx,NOT (bMVSCSI+bMVENHSCSI) ;yes, flush the SCSI bits
or ecx,bMVSONY ;set the 535 bit
@@f6:
; determine if MPU-401 emulation is active
mov edx,COMPATREGE ;compatibility register
xor edx,edi
in al,dx
test al,cpMPUEmulation
jz @@sehw_done
or ecx,bMVMPUEMUL
@@sehw_done:
; loop on a table search to find identify the board
push ebx
mov ebx,-2
@@sehw_05:
add ebx,2
cmp [word ebx+MVProductIDTable],-1
jz @@sehw_bad_hw ;yes, we can't identify this board
mov edx,ecx
and dx,[word ebx+MVDoCareBits]
cmp dx,[word ebx+MVProductIDTable]
jnz @@sehw_05
mov edx,ebx
shr edx,1
pop ebx
movzx edi,di
mov [dword _MVTranslateCode],edi
mov eax,esi
sub ah,ah ;for our purposes, we will return SCSI
xchg ah,al ;into ah
clc ;The board was identified !.
mov [_mvHWVersionBits],cx
jmp @@sehw_exit
@@sehw_bad_hw:
pop ebx
stc
jmp @@sehw_exit
@@sehw_bad:
stc
@@sehw_exit:
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; Detects and identifies the installed Pro AudioSuctrum. ;
; ;
; Entry Conditions: ;
; edi = word address containing the base address. ;
; ;
; Exit Conditions: ;
; Carry is set on error ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc mvGetHWVersion
lea eax,[DACi_freq_convert]
mov [dword CARD_freq_convert],eax
lea eax,[DACi_volume_convert]
mov [dword CARD_volume_convert],eax
or edi,edi
jnz @@mvgehw_05
mov edi,DEFAULT_BASE
call SearchHWVersion
jnc @@mvgehw_exit
mov edi,ALT_BASE_1
call SearchHWVersion
jnc @@mvgehw_exit
mov edi,ALT_BASE_2
call SearchHWVersion
jnc @@mvgehw_exit
mov edi,ALT_BASE_3
@@mvgehw_05:
call SearchHWVersion
@@mvgehw_exit:
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; Initializes the state table pointer. ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc MVInitStatePtr
; setup a pointer to our local hardware state table
lea ebx,[MVHardwareShadowTable]
mov [dword mvhwShadowPointer],ebx
mov [ebx+MVState._audiomixr],31h ;lowest filter setting
mov [ebx+MVState._crosschannel],09h ;cross channel l-2-l, r-2-r
; find the int 2F interface and if found, use it's state table pointer
mov ax,0BC00h ;MVSOUND.SYS ID check
mov bx,'??'
sub cx,cx
sub dx,dx
int 2fh
xor bx,cx
xor bx,dx
cmp bx,'MV'
jnz @@imvsp_done ;no, exit home
mov ax,0BC02H ;get the pointer
int 2fh
cmp ax,'MV'
jnz @@imvsp_done
movzx edx,dx
movzx ebx,bx
shl edx,4
add edx,ebx
push edx
mov ax,0EE02h
int 31h ; returns EBX with program base linear address
pop edx
sub edx,ebx
mov [dword mvhwShadowPointer],edx
@@imvsp_done:
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; Turn off the PCM timers, interrupts, and state machine. ;
; ;
; Entry Conditions: ;
; ;
; Exit Conditions: ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc StopPCM
push edi
mov edi,[mvhwShadowPointer]
; clear the audio filter sample bits
mov edx,AUDIOFILT
xor edx,[_MVTranslateCode]
cli
mov al,[edi+MVState._audiofilt] ;get the state
and al,not (bFIsrate+bFIsbuff) ;flush the sample timer bits
mov [edi+MVState._audiofilt],al ;save the new state
out dx,al
; clear the PCM enable bit
mov al,[edi+MVState._crosschannel] ;get the current cross channel
and al,not bCCenapcm ;clear the PCM enable bit
or al,bCCdac
mov edx,CROSSCHANNEL
xor edx,[_MVTranslateCode]
out dx,al ; end to the hardware
mov [edi+MVState._crosschannel],al
; disable the 16 bit stuff
test [_MVHWVersionBits],bMV101 ;101 chip?
jz @@stpc02 ;no, don't touch this...
mov edx,SYSCONFIG2
xor edx,[_MVTranslateCode]
in al,dx
and al,not bSC216bit+bSC212bit ;flush the 16 bit stuff
out dx,al
@@stpc02:
; clear the appropriate Interrupt Control Register bit
mov ah,[MVTypeOfSetup]
and ah,bICsamprate+bICsampbuff
not ah
mov edx,INTRCTLR
xor edx,[_MVTranslateCode]
in al,dx
and al,ah ;kill sample timer interrupts
out dx,al
mov [edi+MVState._intrctlr],al
; clear the system interrupt mask only if no other ints are used
test al,fICintmaskbits XOR (bICsamprate+bICsampbuff)
jnz @@stpc10
; select the correct IRQ controller, then mask it...
cmp [init_settings.IRQ_no],2 ;Chained IRQ channel?
jz @@stpc10 ;yes, leave it open...
mov dx,IRQ1MASKREG
cmp [init_settings.IRQ_no],8 ;2nd IRQ controller?
jl @@stpc05
mov dl,IRQ2MASKREG
@@stpc05:
in al,dx
or al,[MVTheIRQMask]
out dx,al
sti
@@stpc10:
push edi
cmp [mvStatusWord],0 ;is there any activity?
jz @@kidm_none
mov edi,[PCM_DMAPointer] ;get the DMA pointer
sub dx,dx ;clear out the high byte
; mask out the DMA to stop it
cli
mov al,[edi+dmaaddr._dmach] ;get the adjusted dma channel #
or al,0100b ;disable the DMA
mov dl,[edi+dmaaddr._dmawrsmr]
out dx,al
; remove control on the DRQ line
mov edi,[mvhwShadowPointer]
mov al,[edi+mvstate._crosschannel] ;get the state
mov edx,CROSSCHANNEL
xor edx,[_MVTranslateCode] ;xlate the board address
and al,not bCCdrq ;clear the DRQ bit
out dx,al
mov [edi+mvstate._crosschannel],al ;and save the new state
sti
@@kidm_none:
pop edi
mov [mvStatusWord],0
pop edi
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; Initializes the PCM code ;
; ;
; Entry Conditions: ;
; None ;
; ;
; Exit Conditions: ;
; AX = Version of this Code ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc InitPCM
mov [MVTypeOfSetup],POLLEDMASK ;flushes both interrupts
;for upcoming calls
movsx eax,[byte init_settings.DMA_no] ;initialize the DMA now...
and eax,0111b
mov ebx,eax
shl ebx,1
jnz @@seldma_02
push sp
pop cx
cmp cx,sp
jnz @@seldma_bad
@@seldma_02:
mov dx,[word ebx+@@dmatable]
or dx,dx
jz @@seldma_bad
mov [init_settings.DMA_no],al
mov [byte MVOurDMAPageReg],dh
mov [byte MVOurDMAddress],dl
lea ebx,[DMA1AddrTable]
cmp al,4
jl @@seldma_05
lea ebx,[DMA2AddrTable]
sub al,4
@@seldma_05:
mov [ebx+dmaaddr._dmach],al
mov [dword PCM_DMAPointer],ebx
sub ax,ax
@@seldma_bad:
mov eax,[dword DAC_old_irq_ofs]
or eax,eax
jz @@F1
mov bl,[init_settings.IRQ_no]
mov edx,[dword DAC_old_irq_ofs]
mov cx,[word DAC_old_irq_sel]
call setirqvector
mov [dword DAC_old_irq_ofs],0
mov [word DAC_old_irq_sel],0
@@F1:
sub ax,ax
movsx ecx,[init_settings.IRQ_no] ;initialize the IRQ now... ;get the irq # (2-7,10-12,14-15)
and cl,0fh ;save only the valid bits
mov bx,01
shl bx,cl
and bx,1001110010111100b
jz @@seirqbad
mov [init_settings.IRQ_no],cl
cmp cl,8 ;2nd interrupt controller?
jb @@F3 ;no, skip
xchg bh,bl
@@f3:
mov [mvTheIRQMask],bl
mov eax,[DAC_old_irq_ofs]
or eax,eax
jnz @@F2
mov bl,[init_settings.IRQ_no]
call getirqvector
mov [dword DAC_old_irq_ofs],edx
mov [word DAC_old_irq_sel],cx
@@F2:
mov ax,1
@@seirqbad:
dec ax
call StopPCM ;kill the Audio Spectrum board
mov edx,INTRCTLRST ;flush any pending PCM irq
xor edx,[_MVTranslateCode] ;xlate the board address
out dx,al
ret
label @@dmatable
dw (CH0PAGEREG SHL 8) + DMAC0ADDR
dw (CH1PAGEREG SHL 8) + DMAC1ADDR
dw (CH2PAGEREG SHL 8) + DMAC2ADDR
dw (CH3PAGEREG SHL 8) + DMAC3ADDR
dw 0
dw (CH5PAGEREG SHL 8) + DMA2C5ADDR
dw (CH6PAGEREG SHL 8) + DMA2C6ADDR
dw (CH7PAGEREG SHL 8) + DMA2C7ADDR
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; LoadDMA -- Load the DMA controller to read/write data to the MV board
;
; Entry Conditions:
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc LoadDMA
mov edi,[mvhwShadowPointer]
mov esi,[PCM_DMAPointer] ;point to the DMA controller table
sub dx,dx ;clear out the high byte
; kill the dma until all programming is done
mov al,[esi+dmaaddr._dmach] ;get the adjusted dma channel #
or al,0100b ;causes all DMA to be suspended
mov dl,[esi+dmaaddr._dmawrsmr]
out dx,al
; program the mode
mov al,01011000b ;01011000b ;get the app's desired mode
or al,[esi+dmaaddr._dmach] ;merge the adjusted dma channel #
mov dl,[esi+dmaaddr._dmawrmode]
out dx,al
; adjust the address for a 16 bit channel
mov eax,[dword DAC_PHYSICAL_PAGE]
push eax
shr eax,16
; setup the page register
mov dx,[MVOurDMAPageReg]
out dx,al
mov bl,al
; reset the flip-flop, then output the address, then count
mov dl,[esi+dmaaddr._dmaclear] ;dh is still clear...
out dx,al ;flush...
pop eax
cmp esi,offset DMA1AddrTable ;1st DMA controller?
jz @@F1 ;yes, continue on...
shr bl,1 ;no, divide the buffer in half
rcr ax,1 ;by shifting 17 bits
@@F1:
mov dx,[MVOurDMAddress]
out dx,al
call PCM_pause
xchg ah,al
out dx,al
mov eax,[DMA_Length] ;<------>
lea eax,[eax*2]
cmp esi,offset DMA1AddrTable ;is this the 2nd dma controller?
jz @@lodma03 ;no, use the full length
shr ax,1
inc dx ;move to next port address
@@lodma03:
dec ax
inc dx ;move to next port address
out dx,al
call PCM_pause
xchg ah,al
out dx,al
; before we enable the DMA, let's make sure the DRQ is controlled, not floating
mov al,[edi+mvstate._crosschannel] ;get the state
mov edx,CROSSCHANNEL
xor edx,[_MVTranslateCode]
or al,bCCdrq ;set the DRQ bit to control it
out dx,al
mov [edi+mvstate._crosschannel],al ;and save the new state
; re-enable the dma now that all programming is done
mov al,[esi+dmaaddr._dmach] ;get the adjusted dma channel #
sub dx,dx
mov dl,[esi+dmaaddr._dmawrsmr]
out dx,al ;& let'er loose (not moving though...)
; all done, return home...
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; SetupPCMDMAIO -- Setup to output to the DAC
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc SetupPCMDMAIO
push edi
mov edi,[mvhwShadowPointer]
; setup the sample rate timer
mov al,00110110b ;36h Timer 0 & square wave
mov edx,TMRCTLR
xor edx,[_MVTranslateCode]
pushf
cli
out dx,al ;setup the mode, etc
mov [edi+mvstate._tmrctlr],al
mov ax,[edi+mvstate._samplerate] ;pre-calculated & saved in prior code
mov edx,SAMPLERATE
xor edx,[_MVTranslateCode]
out dx,al ;output the timer value
call PCM_pause
xchg ah,al
out dx,al
popf
; Setup the Sample Buffer Counter Timer (T1 & rate generator)
mov eax,[dword DMA_Length] ;get the count
add eax,1 ;make it 1 based (1 - 64k)
mov bl,[init_settings.DMA_no] ;is this a 16 bit channel?
mov bh,[MVSampleSize] ;CX = sample size, channel
sub cx,cx ;ch = multiplier, cl=divider
cmp bx,0003h ;8 bits on 8 bit channel?
jbe @@mdF1 ;yes, continue on...
inc cx ;divide by 2
cmp bx,0007h ;8 bits on 16 bit channel?
jbe @@mdF1 ;yes, continue on...
xchg ch,cl ;multiply by 2
cmp bx,0203h ;16 bits on 8 bit channel?
jbe @@mdF1 ;yes, continue on...
sub cx,cx ;no multiply or divide
@@mdF1:
dec ax ;<------>
shr ax,cl ;if 8 on 16 divide by 2
xchg ch,cl
shl ax,cl ;if 16 on 8 multiply by 2
sub cx,cx ;The buffer size is # of bytes, so
neg bh ;we must convert it to the data size
adc cx,cx
shr ax,cl
push edi
mov edi,[mvhwShadowPointer]
push edx eax
mov al,01110100b ;74h Timer 1 & rate generator
mov edx,TMRCTLR
xor edx,[_MVTranslateCode]
cli
out dx,al
mov [edi+mvstate._tmrctlr],al ;local timer control register
pop eax
mov edx,SAMPLECNT
xor edx,[_MVTranslateCode]
mov [edi+mvstate._samplecnt],ax
out dx,al
call PCM_pause
xchg ah,al
out dx,al
sti
xchg ah,al
pop edx edi
; Setup the system interrupt mask (IRQ mask)
mov dx,IRQ1MASKREG
cmp [init_settings.IRQ_no],8 ;2nd IRQ controller?
jl @@irqcF2
mov dl,IRQ2MASKREG
@@irqcF2:
in al,dx ;get the mask
mov ah,[mvTheIRQMask]
not ah
and al,ah ;unmask the correct IRQ
out dx,al ;then let the system know
; Setup the Interrupt Control Register
mov edx,INTRCTLRST ;flush any pending interrupts
xor edx,[_MVTranslateCode] ;xlate the board address
out dx,al ;of the PCM circuitry
mov edx,INTRCTLR
xor edx,[_MVTranslateCode] ;xlate the board address
in al,dx ;get the real mask
or al,bICsampbuff ;interrupt on sample buffer count
out dx,al ;send it..
mov [edi+mvstate._intrctlr],al ;save it..
; enable the 12/16 bit stuff
test [_MVHWVersionBits],bMV101 ;101 chip?
jz @@sdhpas1_05 ;no, don't touch this...
mov cx,((NOT(bSC216bit+bSC212bit)) shl 8) + bSC216bit+bSC212bit
cmp [mvSampleSize],1 ;12 bit?
jz @@F3scsi
mov cx,((NOT(bSC216bit+bSC212bit)) shl 8) + bSC216bit
cmp [mvSampleSize],2 ;16 bit?
jz @@F3scsi
mov cx,((NOT(bSC216bit+bSC212bit)) shl 8) + 0
@@f3scsi:
mov edx,SYSCONFIG2
xor edx,[_MVTranslateCode] ;xlate the board address
in al,dx
and al,ch ;clear the bits
or al,cl ;set the appropriate bits
out dx,al
@@sdhpas1_05:
; setup the direction, stereo/mono and DMA enable bits
mov al,bCCmono ;get the stereo/mono mask bit
and al,0 ;al = bCCmono if in mono mode
or al,bCCdac ;bit d6 of interrupt control register
or al,bCCenapcm
mov edx,CROSSCHANNEL
xor edx,[_MVTranslateCode] ;xlate the board address
mov ah,0fh + bCCdrq ;get a mask to load non PCM bits
and ah,[edi+mvstate._crosschannel] ;grab all but PCM/DRQ/MONO/DIRECTION
or al,ah ;merge the two states
xor al,bCCenapcm ;disable the PCM bit
out dx,al ;send to the hardware
xor al,bCCenapcm ;enable the PCM bit
out dx,al ;send to the hardware
mov [edi+mvstate._crosschannel],al ; and save the new state
; Setup the audio filter sample bits
mov al,[edi+mvstate._audiofilt]
or al,bFIsrate+bFIsbuff ;enable the sample count/buff counters
mov edx,AUDIOFILT
xor edx,[_MVTranslateCode] ;xlate the board address
out dx,al
mov [edi+mvstate._audiofilt],al
sti ; fly baby fly !
pop edi
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
label PAS16_sample_settings tDAC_ssetings
tDAC_ssetings <11025,00222,0444,22050>
tDAC_ssetings <16538,00332,0664,33075>
tDAC_ssetings <22050,00442,0884,44100>
tDAC_ssetings <33075,00662,1324,66150>
tDAC_ssetings <44100,00882,1764,88200>
proc StartPlaying
mov [MVTypeOfSetup],DMAMASK
mov [byte DAC_shift_value],6
movzx eax,[byte init_settings.DAC_Samplerate]
mov ecx,size tDAC_ssetings
mul ecx
mov ebx,[dword eax+PAS16_sample_settings.DAC_sr]
mov [dword DAC_sampling_rate],ebx
mov ebx,[dword eax+PAS16_sample_settings.DAC_mix_buffer_size]
mov [dword DAC_mix_buffer_size],ebx
lea ebx,[ebx*4]
mov [DAC_double_buf2],ebx
push eax
mov bl,[init_settings.IRQ_no]
lea edx,[PAS16_virtualmixxer]
mov cx,cs
call setirqvector
pop eax
mov [byte MVSampleSize],2
mov ebx,[dword eax+PAS16_sample_settings.DMA_length]
lea ebx,[ebx*2]
mov [dword DMA_length],ebx
mov eax,[dword eax+PAS16_sample_settings.DMA_real_sr]
mov edi,[mvhwShadowPointer]
mov ecx,eax
mov eax,1193180
xor edx,edx
div ecx
mov [edi+MVState._samplerate],ax
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; Program the DMA, then our board circuitry to start the interrupts
call LoadDMA ;setup the DMA controller
call SetupPCMDMAIO ;Setup the MV Hardware
mov [mvStatusWord],1 ;set the global status word
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc find_pats_seqs
mov [byte funk_info.no_of_sequences],0
mov edi,[funk_hr_ptr] ; find no of patterns
xor al,al
mov ecx,256
@@find_patseq:
cmp [byte edi+tfunk_hr.order_list],0FFh
je @@end_patseq
inc [byte funk_info.no_of_sequences]
cmp [byte edi+tfunk_hr.order_list],al
jbe @@test_next
mov al,[byte edi+tfunk_hr.order_list]
@@test_next:
inc edi
dec ecx
jnz @@find_patseq
@@end_patseq:
dec [byte funk_info.no_of_sequences]
inc al
mov [byte funk_info.no_of_patterns],al
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc resync_sample_ptrs
mov al,[byte init_settings.card_type]
cmp al,SB_CARD
je @@DAC_CARD
cmp al,SBPRO_CARD
je @@DAC_CARD
cmp al,GUS_VARB_CARD
je @@DSP_CARD
cmp al,SB15EM_CARD
je @@DAC_CARD
cmp al,SB16_CARD
je @@DAC_CARD
cmp al,GUS_FIXB_CARD
je @@DSP_CARD
cmp al,PAS16_CARD
je @@DAC_CARD
ret
@@DAC_CARD:
mov eax,[dword funk_sd_ptr]
mov [dword funk_info.sample_ptrs],eax
jmp @@calc
@@DSP_CARD:
mov [dword funk_info.sample_ptrs],32
@@calc:
mov ebx,[funk_hr_ptr]
add ebx,offset (tfunk_hr).funk_sb
xor edi,edi
mov cl,63
@@sync_sp:
mov eax,[dword ebx+tfunk_sb.length]
add eax,[dword edi+funk_info.sample_ptrs]
add ebx,size tfunk_sb
add edi,4
mov [dword edi+funk_info.sample_ptrs],eax
dec cl
jnz @@sync_sp
mov eax,[dword ebx+tfunk_sb.length]
add eax,[dword edi+funk_info.sample_ptrs]
mov [dword funk_info.sample_block_size],eax
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc upload_exteral_data
cmp [byte init_settings.card_type],GUS_VARB_CARD
je @@GUS_mem_move
cmp [byte init_settings.card_type],GUS_FIXB_CARD
je @@GUS_mem_move
ret
@@GUS_mem_move:
call GUS_reset
mov esi,[dword funk_sd_ptr]
mov edi,[dword funk_info.sample_ptrs]
mov ecx,[dword funk_info.sample_block_size]
sub ecx,[dword funk_info.sample_ptrs]
call GUS_upload
call GUS_reset
call GUS_intready
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; eax = header buffer ptr ;
; ebx = sample buffer ptr ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc init_for_play
mov [byte funk_info.trek_status],PLAY
mov [byte funk_info.sequence_ofs_old],0ffh
mov [byte funk_info.pattern_ofs2_old],0ffh
mov [byte funk_info.sequence_ofs],0
mov [byte funk_info.pattern_ofs],0
mov [byte funk_info.tempo],04h
mov [byte funk_info.tempo_count],0
mov [byte funk_info.master_volume],0fh
call find_pats_seqs
lea edi,[funk_chan1]
mov cl,8
@@clear_funk_chan:
;─control system─────────────────
mov [byte edi+tfunk_chan.command],0fh
mov [byte edi+tfunk_chan.com_val],0
mov [byte edi+tfunk_chan.comspd_count],0
mov [byte edi+tfunk_chan.sample],3fh
mov [dword edi+tfunk_chan.start],0ffffffffh
mov [dword edi+tfunk_chan.length],100000h
mov [byte edi+tfunk_chan.funkctrl],0
mov [byte edi+tfunk_chan.port_type],0
mov [byte edi+tfunk_chan.sample_ofs_parm],08h
mov [byte edi+tfunk_chan.vib_waveform],0
mov [byte edi+tfunk_chan.vol_vib_waveform],0
mov [byte edi+tfunk_chan.balance],80h
mov [byte edi+tfunk_chan.retrig_limit],4
mov [byte edi+tfunk_chan.arp_speed],3
;─note system────────────────────
mov [byte edi+tfunk_chan.note_command],0fh
mov [byte edi+tfunk_chan.note_com_val],0
mov [byte edi+tfunk_chan.note_comspd_count],0
mov [byte edi+tfunk_chan.note],03fh
mov [word edi+tfunk_chan.ifreq],0
mov [word edi+tfunk_chan.ifreq_vibrato],0
mov [word edi+tfunk_chan.ifreq_portdest],0
mov [dword edi+tfunk_chan.rfreq],0
mov [dword edi+tfunk_chan.rfreq_adjust],0
mov [dword edi+tfunk_chan.rfreq_portdest],0
mov [byte edi+tfunk_chan.vib_ptr],0
mov [byte edi+tfunk_chan.note_beat_count],0
;─volume system──────────────────
mov [byte edi+tfunk_chan.volume_command],0fh
mov [byte edi+tfunk_chan.volume_com_val],0
mov [byte edi+tfunk_chan.volume_comspd_count],0
mov [byte edi+tfunk_chan.volume],0
mov [byte edi+tfunk_chan.volume_vibrato],0
mov [byte edi+tfunk_chan.volume_portdest],0
mov [byte edi+tfunk_chan.rvolume],0
mov [byte edi+tfunk_chan.vol_vib_ptr],0
mov [byte edi+tfunk_chan.volume_beat_count],0
mov [dword edi+tfunk_chan.CARD_sample_ptr],0
mov [dword edi+tfunk_chan.CARD_freq],0
mov [dword edi+tfunk_chan.CARD_freq_attract],0
mov [dword edi+tfunk_chan.CARD_volume],0
add edi,size tfunk_chan
dec cl
jnz @@clear_funk_chan
call resync_sample_ptrs
mov [byte funk_info.trek_status],STOP
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; AUTODETECT CODE ;
; ;
; process: ;
; ;
; a) it does PORT detection tests for the following cards (in order): ;
; - PAS16 ;
; - GUS CARD ;
; - Creative Labs cards ;
; ;
; if a particular card is found, then the routines then determine IRQ, ;
; and DMA settings of the card. ;
; ;
; PAS16: it first tests for a driver called "MVSOUND.SYS", which always ;
; resides with any PAS card. If it can't find the driver, then it ;
; assumes that the card isn't there. All information is obtained through ;
; this driver. ;
; To my knowledge, most software will not work without this driver. ;
; ;
; GUS: AS far as i know, the ULTRASND= environment setting has been set ;
; for every single GUS card ever installed. It is assumed that every ;
; computer that has a GUS card will have ULTRASND= env. setting as well. ;
; DMA and IRQ information is extracted from this env setting. If it can't ;
; find it, then the detection routine will fail. ;
; ;
; CT: After is has done a PORT test, it then determines the DSP version ;
; of the card. This will determine if it's a SB, SBPRO, SB16 etc. Once ;
; this is determined, it will go about searching for IRQ and DMA in the ;
; following way: ;
; ;
; SB1.SB20,SBPRO,SBPRO2: The BLASTER= env. setting is searched for ;
; IRQ and DMA settings. If it can't find this enc setting, then the ;
; detection routine will fail. ;
; ;
; SB16 and AWE32: Because these cards have software configurable IRQ and ;
; DMA settings, the port status registers are read to determine these ;
; settings. The routines will also detect the POST address of the ;
; MPU-401 hardware. ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ad_line1 db 13,10,13,10,"Detecting card: $"
ad_line2 db "Couldn't find IRQ?"
ad_enter db 13,10,"$"
ad_line3 db "Couldn't find DMA?",13,10,"$"
ad_line4 db "Found IRQ: $"
ad_line5 db "Found DMA: $"
ad_line6 db "MPU-401 port found at: $"
ad_line7 db "300h",13,10,"$"
ad_line8 db "Searching BLASTER environment...",13,10,"$"
ad_line9 db "Corrupted environment settings...can't find settings.",13,10,"$"
ad_line10 db "Found MIDI IRQ: $"
str_card0 db "Creative Labs compatable card detected at port: 2"
str_card0_dig db "10h",13,10,"$"
str_card1 db "SoundBlaster 1.X$"
str_card2 db "SoundBlaster 2.0$"
str_card3 db "SoundBlaster PRO$"
str_card4 db "SoundBlaster 16$"
str_card5 db "Gravis Ultrasnd card detected at port: 2"
str_card5_dig db "10h",13,10,"$"
str_card19 db "not"
str_card20 db " detected.",13,10,"$"
str_sel1 db "Multipal cards detected. Please select one of the following.",13,10,13,10,"$"
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; eax= number
proc print_dec
mov esi,4*2
mov ecx,eax
@@dec83:
mov eax,ecx
xor edx,edx
div [dword esi+@@Dec_divider]
mov ecx,edx
add al,'0'
mov ah,0EH
mov bl,7
int 10H
sub esi,4
jge @@dec83
ret
@@dec_divider:
dd 1,10
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc display_irq_dma
mov edx,offset ad_line4
mov ah,9
int 21h
movzx eax,[byte init_settings.IRQ_no]
call print_dec
mov edx,offset ad_enter
mov ah,9
int 21h
mov edx,offset ad_line5
mov ah,9
int 21h
movzx eax,[byte init_settings.DMA_no]
call print_dec
mov edx,offset ad_enter
mov ah,9
int 21h
ret
endp
proc CT_environment
mov edx,offset ad_line8
mov ah,9
int 21h
push es
mov ax,0EE02h ; get DOS32 address info
int 31h ; returns Environment address in EDI
mov ecx,10000h
@@SrchEnvrLoop:
lea esi,[@@blaster_string]
mov ecx,8
repe cmpsb
jne @@No_SBstring
dec edi
mov ebx,edi
xor ecx,ecx
@@s_irq:
cmp [byte ebx],"I"
je @@s_irq_exit
inc ebx
dec cx
jnz @@s_irq
jmp @@No_BLASTER
@@s_irq_exit:
mov al,[byte ebx+1]
sub al,"0"
jnz @@set_irq
mov al,10
xor ecx,ecx
@@set_irq:
mov [byte init_settings.IRQ_no],al
mov ebx,edi
dec cx
@@s_dma:
cmp [byte ebx],"D"
je @@s_dma_exit
inc ebx
dec cx
jnz @@s_dma
@@s_dma_exit:
mov al,[byte ebx+1]
sub al,"0"
mov [byte init_settings.DMA_no],al
call display_irq_dma
pop es
ret
@@No_SBstring:
xor al,al
mov ecx,400h
repne scasb
and ecx,ecx
jz @@No_BLASTER
cmp [byte es:edi],0
jnz @@SrchEnvrLoop
@@No_BLASTER:
mov edx,offset ad_line9
mov ah,9
int 21h
pop es
mov [byte init_settings.card_type],0ffh
ret
@@blaster_string:
db "BLASTER="
endp
proc CT_detect
mov [dword init_settings.PORT_no],210h
call SB_detect_port
jnc @@detected
mov [dword init_settings.PORT_no],220h
call SB_detect_port
jnc @@detected
mov [dword init_settings.PORT_no],230h
call SB_detect_port
jnc @@detected
mov [dword init_settings.PORT_no],240h
call SB_detect_port
jnc @@detected
mov [dword init_settings.PORT_no],250h
call SB_detect_port
jnc @@detected
mov [dword init_settings.PORT_no],260h
call SB_detect_port
jnc @@detected
mov [dword init_settings.PORT_no],280h
call SB_detect_port
jnc @@detected
stc
ret
@@detected:
mov eax,[dword init_settings.PORT_no]
sub eax,210h
shr eax,4
add [byte str_card0_dig],al
mov edx,offset str_card0
mov ah,9
int 21h
mov al,0e1h
call SB_write_dac
call SB_read_dac
mov ah,al
call SB_read_dac
cmp ah,1
je @@sb15
cmp ah,2
je @@sb20
cmp ah,3
je @@sbpro
cmp ah,4
jae @@sb16
ret
@@sb15:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov [byte init_settings.card_type],SB15EM_CARD
mov edx,offset str_card1
mov ah,9
int 21h
mov edx,offset str_card20
mov ah,9
int 21h
call CT_environment
jmp @@done
ret
@@sb20:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
cmp al,0
ja @@sb202
ret
@@sb202:
mov [byte init_settings.card_type],SB_CARD
mov edx,offset str_card2
mov ah,9
int 21h
mov edx,offset str_card20
mov ah,9
int 21h
call CT_environment
jmp @@done
ret
@@sbpro:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov [byte init_settings.card_type],SBPRO_CARD
mov edx,offset str_card3
mov ah,9
int 21h
mov edx,offset str_card20
mov ah,9
int 21h
call CT_environment
jmp @@done
ret
@@sb16:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov [byte init_settings.card_type],SB16_CARD
mov edx,offset str_card4
mov ah,9
int 21h
mov edx,offset str_card20
mov ah,9
int 21h
mov al,80h ; get IRQ
call SB_read_mixer
test al,1
jne @@sb16_irq2
test al,2
jne @@sb16_irq5
test al,4
jne @@sb16_irq7
test al,8
jne @@sb16_irq10
mov [byte init_settings.card_type],0ffh
mov edx,offset ad_line2
mov ah,9
int 21h
jmp @@done
@@sb16_irq2:
mov [byte init_settings.IRQ_no],2
jmp @@sb16_get_dma
@@sb16_irq5:
mov [byte init_settings.IRQ_no],5
jmp @@sb16_get_dma
@@sb16_irq7:
mov [byte init_settings.IRQ_no],7
jmp @@sb16_get_dma
@@sb16_irq10:
mov [byte init_settings.IRQ_no],10
@@sb16_get_dma:
mov al,81h ; get DMA
call SB_read_mixer
test al,32
jne @@sb16_dma5
test al,64
jne @@sb16_dma6
test al,128
jne @@sb16_dma7
mov [byte init_settings.card_type],0ffh
mov edx,offset ad_line3
mov ah,9
int 21h
jmp @@done
@@sb16_dma5:
mov [byte init_settings.DMA_no],5
jmp @@display_sb16
@@sb16_dma6:
mov [byte init_settings.DMA_no],6
jmp @@display_sb16
@@sb16_dma7:
mov [byte init_settings.DMA_no],7
@@display_sb16:
call display_irq_dma
mov edx,offset ad_line6
mov ah,9
int 21h
mov [MPU_addr],300h
call MPU401_Reset
or al,al
jz @@mpu_found
mov [MPU_addr],330h
call MPU401_Reset
or al,al
jnz @@mpu_notfound
@@mpu_found:
mov eax,[MPU_addr]
sub eax,300h
shr eax,4
add [byte ad_line7+1],al
mov edx,offset ad_line7
mov ah,9
int 21h
jmp @@done
@@mpu_notfound:
mov edx,offset str_card19
mov ah,9
int 21h
@@done:
ret
endp
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; cy = not detected ;
; cn = detected ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc GUS_environment
push es
mov ax,0EE02h ; get DOS32 address info
int 31h ; returns Environment address in EDI
cld
mov ecx,10000h
@@SrchEnvrLoop:
lea esi,[@@ultrasnd_string]
mov ecx,9
repe cmpsb
jne @@No_GUSstring
mov [byte init_settings.card_type],GUS_FIXB_CARD
mov ebx,[es: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 ;eeax = char digit in al
mov edx,eax ;load port address
shl edx,4
add edx,200h
sub al,1h ;port must be between 210h .. 260h
cmp al,5h
ja @@No_ULTRASND
mov [dword init_settings.PORT_no],edx
add edi,4
xor ecx,ecx
movzx eax,[byte es:edi]
call @@get_digit
cmp [byte eax+GUS_dma_table],0
je @@No_ULTRASND
mov [byte init_settings.DMA_no],al ;get playback DMA
inc edi
cmp [byte es:edi],','
jne @@No_ULTRASND
inc edi
movzx eax,[byte es:edi]
call @@get_digit
cmp [byte eax+GUS_dma_table],0
je @@No_ULTRASND
mov [byte init_settings.DMA_no2],al ;DMA record channel
inc edi
cmp [byte es:edi],','
jne @@No_ULTRASND
xor ebx,ebx
inc edi
cmp [byte es:edi],'1'
jne @@J61
mov bl,10
inc edi
@@J61:
mov eax,[es:edi]
call @@get_digit
add al,bl
cmp al,15
ja @@No_ULTRASND
cmp [byte eax+GUS_irq_table],0
je @@No_ULTRASND
mov BL,AL
mov [byte init_settings.IRQ_no],al
inc edi
cmp [byte es:edi],','
jne @@No_ULTRASND
inc edi
cmp [byte es:edi],'1'
jne @@J62
mov BH,10
inc edi
@@J62:
mov al,[es:edi]
call @@get_digit
add al,bh
cmp al,15
ja @@No_ULTRASND
cmp [byte eax+GUS_irq_table],0
je @@No_ULTRASND
mov [byte init_settings.IRQ_no2],al ;MIDI irq number
inc edi
cmp [byte es:edi],','
je @@got_it
cmp [byte es:edi],' '
je @@got_it
cmp [byte es:edi],0
jne @@No_ULTRASND
@@got_it:
pop es
mov edx,offset ad_line4
mov ah,9
int 21h
movzx eax,[byte init_settings.IRQ_no]
call print_dec
mov edx,offset ad_enter
mov ah,9
int 21h
mov edx,offset ad_line10
mov ah,9
int 21h
movzx eax,[byte init_settings.IRQ_no2]
call print_dec
mov edx,offset ad_enter
mov ah,9
int 21h
ret
@@No_GUSstring:
mov al,0 ; scan environment for next ZERO
mov ecx,400h
repne scasb
or ecx,ecx
jz @@No_ULTRASND
cmp [byte es:edi],0 ; if double zeros then finished
jnz @@SrchEnvrLoop
@@No_ULTRASND:
pop es
mov edx,offset ad_line9
mov ah,9
int 21h
mov [byte init_settings.card_type],0ffh
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 es
ret
@@ULTRASND_string:
db 'ULTRASND='
endp
proc GUS_detect
mov [dword init_settings.PORT_no],210h
call GUS_detect_port
jnc @@detected
mov [dword init_settings.PORT_no],220h
call GUS_detect_port
jnc @@detected
mov [dword init_settings.PORT_no],230h
call GUS_detect_port
jnc @@detected
mov [dword init_settings.PORT_no],240h
call GUS_detect_port
jnc @@detected
mov [dword init_settings.PORT_no],250h
call GUS_detect_port
jnc @@detected
mov [dword init_settings.PORT_no],260h
call GUS_detect_port
jnc @@detected
ret
proc GUS_detect_port
mov [dword gus_base],0
mov [dword gus_status],6
mov [dword gus_timercontrol],8
mov [dword gus_timerdata],9
mov [dword gus_irqdmacontrol],0bh
mov [dword gus_midictrl],100h
mov [dword gus_mididata],101h
mov [dword gus_voice],102h
mov [dword gus_command],103h
mov [dword gus_datalo],104h
mov [dword gus_datahi],105h
mov [dword gus_GF1_status],106h
mov [dword gus_dram],107h
mov eax,[dword init_settings.PORT_no]
add [dword gus_base],eax
add [dword gus_Status],eax
add [dword gus_timercontrol],eax
add [dword gus_timerdata],eax
add [dword gus_irqdmacontrol],eax
add [dword gus_midictrl],eax
add [dword gus_mididata],eax
add [dword gus_voice],eax
add [dword gus_Command],eax
add [dword gus_DataLo],eax
add [dword gus_DataHi],eax
add [dword gus_GF1_status],eax
add [dword gus_dram],eax
lea eax,[GUSi_freq_convert]
mov [dword CARD_freq_convert],eax
lea eax,[GUSi_volume_convert]
mov [dword CARD_volume_convert],eax
mov edx,[dword gus_command]
mov al,4Ch
out dx,al
add edx,2
xor al,al
out dx,al
call gus_Delay
call gus_Delay
mov edx,[dword gus_command]
mov al,4Ch
out dx,al
add edx,2
mov al,1
out dx,al
mov al,0AAh
xor edi,edi
call gus_mem_out
mov edi,100h
mov al,55h
call gus_mem_out
xor esi,esi
call gus_mem_in
push eax
mov edx,[dword gus_command]
mov al,4Ch
out dx,al
add edx,2
mov al,1
out dx,al
pop eax
cmp al,0AAh
jnz @@Nope
clc
ret
@@Nope:
stc
ret
endp
@@detected:
mov eax,[dword init_settings.PORT_no]
sub eax,210h
shr eax,4
add [byte str_card5_dig],al
mov edx,offset str_card5
mov ah,9
int 21h
call GUS_environment
cmp [byte init_settings.card_type],0ffh
je @@ignore
call GUS_find_mem
@@ignore:
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; cy = not detected ;
; cn = detected ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proc PAS_detect
xor edi,edi
call mvGetHWVersion
jnc @@detected
mov [byte init_settings.card_type],0ffh
ret
@@detected:
mov [byte init_settings.card_type],PAS16_CARD
call MVInitStatePtr
ret
endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; Interface routines ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;bl = card override: 0=PAS,1=GUS,2=CT card
proc FNK_autodetect
cmp bl,1
je @@gus_d
cmp bl,2
je @@ct_d
call PAS_detect
cmp [byte init_settings.card_type],0ffh
jne @@card_detected
@@gus_d:
call GUS_detect
cmp [byte init_settings.card_type],0ffh
jne @@card_detected
@@ct_d:
call CT_detect
cmp [byte init_settings.card_type],0ffh
jne @@card_detected
cmp [byte init_settings.card_type],0ffh
stc
ret
@@card_detected:
clc
ret
endp
;eax = DMA buffer ptr
proc FNK_card_init
add [dword DAC_mix_buffer],eax
add [dword DAC_mix_buffer_right],eax
add [dword DAC_mix_buffer2],eax
push eax
mov ax,0EE02h
int 31h
neg ebx
pop eax
sub eax,ebx
add [dword DAC_PHYSICAL_PAGE],eax
mov edi,[dword DAC_mix_buffer] ; clear buffers
mov ecx,1000h/2
mov eax,8000h
rep stosw
mov edi,[dword DAC_mix_buffer_right] ; clear buffers
mov ecx,1000h/2
mov eax,8000h
rep stosw
mov ecx,2000h
mov edi,[dword DAC_mix_buffer2]
mov al,80h
rep stosb
cmp [byte init_settings.card_type],SB_CARD
je @@sb08
cmp [byte init_settings.card_type],SBPRO_CARD
je @@sb08
cmp [byte init_settings.card_type],GUS_VARB_CARD
je @@gus
cmp [byte init_settings.card_type],SB15EM_CARD
je @@sb08
cmp [byte init_settings.card_type],SB16_CARD
je @@sb16
cmp [byte init_settings.card_type],GUS_FIXB_CARD
je @@gus
cmp [byte init_settings.card_type],PAS16_CARD
je @@pas_family
ret
@@sb08:
call SB08_init
jc @@sb08_e
call SB08_deinit
call SB08_init
@@sb08_e:
ret
@@sb16:
mov ecx,2000h/2
mov edi,[dword DAC_mix_buffer2]
xor eax,eax
rep stosw
call SB16_init
ret
@@gus:
call GUS_init
ret
@@pas_family:
mov ecx,2000h/2
mov edi,[dword DAC_mix_buffer2]
xor eax,eax
rep stosw
call InitPCM
call StartPlaying
ret
endp
proc FNK_card_deinit
cmp [byte init_settings.card_type],SB_CARD
je @@sb08
cmp [byte init_settings.card_type],SBPRO_CARD
je @@sb08
cmp [byte init_settings.card_type],GUS_VARB_CARD
je @@gus
cmp [byte init_settings.card_type],SB15EM_CARD
je @@sb08
cmp [byte init_settings.card_type],SB16_CARD
je @@sb16
cmp [byte init_settings.card_type],GUS_FIXB_CARD
je @@gus
cmp [byte init_settings.card_type],PAS16_CARD
je @@pas_family
ret
@@sb08:
call SB08_deinit
ret
@@sb16:
call SB16_deinit
ret
@@gus:
call GUS_deinit
ret
@@pas_family:
call StopPCM
ret
endp
;eax = funksong pointer
proc FNK_setup_player
mov [funk_hr_ptr],eax
call find_pats_seqs
movzx ecx,[byte funk_info.no_of_patterns]
mov eax,600h
mul ecx
mov ebx,size tfunk_hr
add ebx,eax
mov eax,[funk_hr_ptr]
add ebx,eax
mov [funk_sd_ptr],ebx
call init_for_play
call upload_exteral_data
ret
endp
proc FNK_PLAY
mov [byte funk_info.trek_status],PLAY
ret
endp
proc FNK_STOP
mov [byte funk_info.trek_status],STOP
ret
endp
proc FNK_teststatus
cmp [byte funk_info.trek_status],PLAY
ret
endp
;al = master volume (0-f)
proc FNK_set_mvolume
mov [byte funk_info.master_volume],al
ret
endp
;returns al = master volume (0-f)
proc FNK_get_mvolume
mov al,[byte funk_info.master_volume]
ret
endp