FreqStart = 156h ; low end of frequency in each octave FreqEnd = 2aeh ; high end of frequency in each octave FreqRange = FreqEnd-FreqStart WrkBuff_TrackBase equ 0 ;Pointer to each track WrkBuff_TrackPtr equ 480h ;Offsets in current tracks WrkBuff_TrackDelay equ 492h ;Delay for current tracks WrkBuff_CurrPtn equ 49Bh ; WrkBuff_CurrLine equ 49Ch ; WrkBuff_SongDelay equ 49Dh ; WrkBuff_CurrSpeed equ 49Eh ; WrkBuff_CurrEvent equ 49Fh ;privat Buffer!!! WrkBuff_LastEvent equ 4A4h ; WrkBuff_CarrVol equ 510h WrkBuff_ModVol equ 519h WrkBuffSize equ 522h _AdlibState db 0 ;set to zero if adlib not detected!!! ev_pitch equ 0 ev_oct equ 1 ev_sam equ 2 ev_cmd equ 3 ev_params equ 4 ev_vol equ 5 ;lastvol ev_arpeggio equ 6 ev_pitching equ 7 ev_tpdest equ 9 ev_lastparams equ 11 ;for TonePortamento and stuff!!! LastEventSize equ 12 FreqParams dw 343,363,385,408,432,458,485,514,544,577,611,647 oldint08 dw 0,0 ModPtr dw 0,0 WrkPtr dw 0,0 ;----- InitAdlib ---------- ; ; This proc fills the work buffer with pointers, defaults and stuff. ; Call this to create a buffer for a tune!!! ; ;ds:si = Modulepointer ;es:di = Workbuffer ;al = playmode (0=interrupt 1=polling) _InitAdlib proc near pusha push ax mov cs:[ModPtr],si mov ax,ds mov cs:[ModPtr+2],ax mov cs:[WrkPtr],di mov ax,es mov cs:[WrkPtr+2],ax call Adlib_Reset ;---- Clear Workbuffer push di xor ax,ax mov cx,WrkBuffSize/2 rep stosw pop di ;---- Init trackpointer mov bl,ds:[si+933] ;number of patterns inc bl xor bh,bh imul bx,18 lea si,[si+bx+1072] ;offset of the tracks lodsw mov cx,ax ia_GetTrackPtrLoop: lodsw ;read trackposition mov bx,ax add bx,bx mov es:[di+bx],si ;store pointer into trackptrtab! xor dl,dl ia_SearchNextTrack: lodsb test al,128 jnz ia_Jump lodsw inc dl jmp ia_GetNextEvent ia_Jump: and al,127 add dl,al ia_GetNextEvent: cmp dl,64 jb ia_SearchNextTrack loop ia_GetTrackPtrLoop mov word ptr es:[di+WrkBuff_SongDelay],0606h ;default tempo!!! pop ax mov cs:[irqmod],al cmp al,1 jz ia_PollingMode ;---- Init the Timer-IRQ cli mov ax,3508h int 21h mov cs:[oldint08],bx mov cs:[oldint08+2],es mov ax,2508h push cs pop ds mov dx,offset TimerProc int 21h mov ax,5D37h ;50Hz out 40h,al mov al,ah out 40h,al sti ia_PollingMode: popa ret _InitAdlib endp _StopAdlib proc near push ds cmp cs:[irqmod],1 jz sa_Polling cli mov al,-1 out 40h,al out 40h,al mov ax,2508h push cs:[oldint08+2] pop ds mov dx,cs:[oldint08] int 21h sti sa_Polling: call Adlib_Reset pop ds ret _StopAdlib endp irqmod db 0 time dw 0 ;16:16 dw 0 timeadd dd 5D37h ;16:16 TimerProc proc near push eax ds es si di lds si,dword ptr cs:[ModPtr] les di,dword ptr cs:[WrkPtr] call _AdlibPlayer mov eax,cs:timeadd add dword ptr cs:time,eax mov al,20h out 20h,al pop di si es ds eax iret TimerProc endp ;------ Adlib Player -------- ; ; This is the mainfunction of the player jump into this code 50 times a sec. ; (or what ever your songtempo is) ; ;ds:si = Modulepointer ;es:di = Workbuffer _AdlibPlayer proc near cmp cs:[_AdlibState],0 jz ap_NoAdlibPresent pusha mov al,byte ptr es:[di+WrkBuff_SongDelay] dec al jnz ap_JustDoTheFX mov al,byte ptr es:[di+WrkBuff_CurrSpeed] mov byte ptr es:[di+WrkBuff_SongDelay],al cmp byte ptr es:[di+WrkBuff_CurrLine],0 jnz ap_ContPtn call CalcTrackPtr ap_ContPtn: mov cs:[breakstate],0 xor cx,cx ap_ChannelLoop: mov bx,cx mov al,byte ptr es:WrkBuff_TrackDelay[di+bx] and al,127 jz ap_TryToGetEvent dec byte ptr es:WrkBuff_TrackDelay[di+bx] jmp ap_StillWaiting ap_TryToGetEvent: mov byte ptr es:WrkBuff_TrackDelay[di+bx],0 add bx,bx mov bp,es:WrkBuff_TrackPtr[di+bx] mov al,ds:[bp] ;Is it a delay??? Then wait!!! test al,128 jz ap_NewEvent dec al inc word ptr es:WrkBuff_TrackPtr[di+bx] mov bx,cx mov byte ptr es:WrkBuff_TrackDelay[di+bx],al jmp ap_StillWaiting ap_NewEvent: add word ptr es:WrkBuff_TrackPtr[di+bx],3 ;---- Decode current event mov byte ptr es:[di+WrkBuff_CurrEvent+ev_params],al mov ax,ds:[bp+1] mov dl,al and dl,0Fh mov byte ptr es:[di+WrkBuff_CurrEvent+ev_cmd],dl mov dx,ax shr dx,4 and dl,11111b mov byte ptr es:[di+WrkBuff_CurrEvent+ev_sam],dl mov al,ah shr al,1 and al,7 mov byte ptr es:[di+WrkBuff_CurrEvent+ev_oct],al shr ah,4 mov byte ptr es:[di+WrkBuff_CurrEvent+ev_pitch],ah ;############# update channel !! ########### imul bp,cx,LastEventSize ;--- change instrument??? mov al,es:[di+WrkBuff_CurrEvent+ev_sam] or al,al jz uc_NoInstrChange mov es:[di+WrkBuff_LastEvent+ev_sam+bp],al ;update instrument mov byte ptr es:[di+WrkBuff_LastEvent+ev_vol+bp],3Fh uc_NoInstrChange: ;--- change the pitch??? mov al,es:[di+WrkBuff_CurrEvent+ev_pitch] or al,al jz uc_NoPitch cmp byte ptr es:[di+WrkBuff_CurrEvent+ev_cmd],8 jz uc_NoPitch mov es:[di+WrkBuff_LastEvent+ev_pitch+bp],al ;update pitch mov al,es:[di+WrkBuff_CurrEvent+ev_oct] mov es:[di+WrkBuff_LastEvent+ev_oct+bp],al ;--- play the new note! mov word ptr es:[di+WrkBuff_LastEvent+ev_Pitching+bp],0 jmp uc_Ready uc_NoPitch: call SetChannelVol uc_Ready: ;ready with updating the channel!!! ;---- Check the FX mov bx,es:[di+WrkBuff_CurrEvent+ev_cmd] mov es:[di+WrkBuff_LastEvent+ev_cmd+bp],bx or bh,bh jz uc_NoNewLastParam mov es:[di+WrkBuff_LastEvent+ev_lastparams+bp],bh uc_NoNewLastParam: mov ax,bx and bx,0Fh add bx,bx mov dx,cs:[CmdPtrTab1+bx] or dx,dx jz amd_NoCommand push cx call dx pop cx amd_NoCommand: cmp byte ptr es:[di+WrkBuff_CurrEvent+ev_cmd],8 jz ap_StillWaiting cmp byte ptr es:[di+WrkBuff_CurrEvent+ev_pitch],0 jz ap_StillWaiting call PlayNote ap_StillWaiting: inc cx cmp cx,9 jb ap_ChannelLoop ;---- Go next line ! cmp cs:[breakstate],0 jz ap_GoNormal mov al,cs:[breakptn] mov byte ptr es:[di+WrkBuff_CurrPtn],al mov al,cs:[breakline] mov byte ptr es:[di+WrkBuff_CurrLine],al or al,al jz ap_CheckSongLoop ;--- Calculate offset into new pattern call CalcTrackPtr xor bx,bx ap_CalcOffsLoop: mov bp,es:[di+WrkBuff_TrackPtr+bx] xor ch,ch mov cl,byte ptr es:[di+WrkBuff_CurrLine] xor dh,dh ;dh=trackdelay ap_RowLoop: or dh,dh jz ap_GetNewEvent dec dh jmp ap_GoOn ap_GetNewEvent: mov al,ds:[bp] test al,128 jnz ap_MakeDelay add bp,3 xor dh,dh jmp ap_GoOn ap_MakeDelay: inc bp and al,127 dec al mov dh,al ap_GoOn: inc ch cmp ch,cl jb ap_RowLoop mov es:[di+WrkBuff_TrackPtr+bx],bp mov bp,bx shr bp,1 or dh,128 mov es:[di+WrkBuff_TrackDelay+bp],dh add bl,2 cmp bl,18 jb ap_CalcOffsLoop jmp ap_CheckSongLoop ap_GoNormal: inc byte ptr es:[di+WrkBuff_CurrLine] cmp byte ptr es:[di+WrkBuff_CurrLine],64 jb ap_ByeBye mov byte ptr es:[di+WrkBuff_CurrLine],0 inc byte ptr es:[di+WrkBuff_CurrPtn] ap_CheckSongLoop: mov al,byte ptr es:[di+WrkBuff_CurrPtn] cmp ds:[si+932],al ja ap_ByeBye mov word ptr es:[di+WrkBuff_CurrPtn],0 ap_ByeBye: popa ap_NoAdlibPresent: ret ap_JustDoTheFX: mov byte ptr es:[di+WrkBuff_SongDelay],al ;---- Check the FX xor cx,cx xor bp,bp ap_FXLoop: mov bx,cx test byte ptr es:WrkBuff_TrackDelay[di+bx],128 jnz ap_DontDoIt mov bx,es:[di+WrkBuff_LastEvent+ev_cmd+bp] mov ax,bx and bx,0Fh add bx,bx mov dx,cs:[CmdPtrTab2+bx] or dx,dx jz ap_DontDoIt push cx call dx pop cx ap_DontDoIt: add bp,LastEventSize inc cx cmp cx,9 jb ap_FXLoop jmp ap_ByeBye _AdlibPlayer endp Adlib_Reset proc near ;*** Check Adlib *** mov dx,388h mov al,2 out dx,al jmp $+2 inc dl mov al,1 out dx,al ;set timer#1 jmp $+2 dec dl in al,dx and al,01000000b ;received?? jz ar_CardOK ret ar_CardOK: mov cs:[_AdlibState],1 mov bx,1 ar_ResetLoop: mov ax,bx and al,0E0h cmp al,40h jnz ar_ClearReg mov ah,63 ar_ClearReg: mov al,bl call Adlib_OUT inc bl jnz ar_ResetLoop mov ax,02001h call Adlib_OUT ret Adlib_Reset endp CalcTrackPtr proc near mov bl,es:[di+WrkBuff_CurrPtn] xor bh,bh mov bl,ds:[si+bx+3A6h] ;current pattern imul bx,18 mov cx,9 lea bp,WrkBuff_TrackPtr[di] ctp_ChLoop: push bx mov bx,ds:[si+bx+430h] ;current track add bx,bx mov ax,es:[di+bx] mov bx,cx mov byte ptr es:[di+WrkBuff_TrackDelay-1+bx],0 pop bx mov es:[bp],ax ;store trackptr add bp,2 add bx,2 dec cl jnz ctp_ChLoop ret CalcTrackPtr endp CmdPtrTab1 dw offset InitArpeggio dw offset SlideFreqUp dw offset SlideFreqDown dw 0 dw offset SetInsVol dw offset JumpPattern dw offset PtnBreak dw offset SetSongSpeed dw offset InitTonePortamento dw offset ExtCmds dw 0 dw 0 dw 0 dw 0 dw 0 dw 0 ;###### Commands Type#1 ####### ; ;ah = Parameter of the Command ;es:[bp] = LastEvent InitArpeggio: mov byte ptr es:[di+WrkBuff_LastEvent+ev_arpeggio+bp],0 ret SetInsVol: mov byte ptr es:[di+WrkBuff_LastEvent+ev_vol+bp],ah call SetChannelVol ret SetSongSpeed: or ah,ah jz sss_Zero cmp ah,32 jb sss_Delay sss_Freq: ;change interrupt frequence cmp cs:[irqmod],1 jz sss_polling mov cl,ah xor ch,ch mov dx,0012h mov ax,34DCh div cx jmp sss_Set sss_Zero: mov ax,-1 sss_Set: mov word ptr cs:timeadd,ax out 40h,al mov al,ah out 40h,al sss_polling: ret sss_Delay: ;just change the delay value mov es:[di+WrkBuff_CurrSpeed],ah mov byte ptr es:[di+WrkBuff_SongDelay],ah ret SlideFreqUp: mov bl,cl mov al,byte ptr es:[di+WrkBuff_LastEvent+ev_pitch+bp] mov dh,byte ptr es:[di+WrkBuff_LastEvent+ev_oct+bp] call GetFreq mov dx,ax mov cl,byte ptr es:[di+WrkBuff_LastEvent+ev_params+bp] xor ch,ch add word ptr es:[di+WrkBuff_LastEvent+ev_pitching+bp],cx add ax,word ptr es:[di+WrkBuff_LastEvent+ev_pitching+bp] cmp ax,FreqRange*7+305 jb sfu_OK mov ax,FreqRange*7+305 sub ax,dx mov word ptr es:[di+WrkBuff_LastEvent+ev_pitching+bp],ax mov ax,FreqRange*7+305 sfu_OK: call SetFreq ret SlideFreqDown: mov bl,cl mov al,byte ptr es:[di+WrkBuff_LastEvent+ev_pitch+bp] mov dh,byte ptr es:[di+WrkBuff_LastEvent+ev_oct+bp] call GetFreq mov dx,ax mov cl,byte ptr es:[di+WrkBuff_LastEvent+ev_params+bp] xor ch,ch sub word ptr es:[di+WrkBuff_LastEvent+ev_pitching+bp],cx add ax,word ptr es:[di+WrkBuff_LastEvent+ev_pitching+bp] or ax,ax jns short sfd_OK not dx mov word ptr es:[di+WrkBuff_LastEvent+ev_pitching+bp],dx xor ax,ax sfd_OK: call SetFreq ret SetCarrModVol proc near mov al,es:[di+WrkBuff_CurrEvent+ev_params] xor ah,ah mov dl,10 div dl or al,al jz short scmv_SetMod mov dh,ah xor ah,ah mov dl,7 mul dl xor al,03Fh xor al,al mov es:[di+WrkBuff_CarrVol+bx],al mov ah,dh scmv_SetMod: or ah,ah jz scmv_byebye mov al,ah xor ah,ah mov dl,7 mul dl xor al,3Fh mov es:[di+WrkBuff_ModVol+bx],al scmv_byebye: ret SetCarrModVol endp InitTonePortamento: mov al,byte ptr es:[di+WrkBuff_CurrEvent+ev_pitch] or al,al jz itp_NoPitch mov dh,byte ptr es:[di+WrkBuff_CurrEvent+ev_oct] call GetFreq mov word ptr es:[di+WrkBuff_LastEvent+ev_tpdest+bp],ax call TonePortamento itp_NoPitch: ret TonePortamento: push si push cx mov si,word ptr es:[di+WrkBuff_LastEvent+ev_tpdest+bp] mov al,byte ptr es:[di+WrkBuff_LastEvent+ev_pitch+bp] xor ah,ah mov dh,byte ptr es:[di+WrkBuff_LastEvent+ev_oct+bp] call GetFreq mov dx,ax mov bx,word ptr es:[di+WrkBuff_LastEvent+ev_pitching+bp] add dx,bx xor ch,ch mov cl,byte ptr es:[di+WrkBuff_LastEvent+ev_lastparams+bp] cmp dx,si ja tp_down jb tp_up tp_byebye: mov word ptr es:[di+WrkBuff_LastEvent+ev_pitching+bp],bx mov ax,dx pop bx pop si call SetFreq ret tp_up: add bx,cx add dx,cx cmp dx,si jbe tp_byebye mov dx,si mov cx,dx sub cx,ax mov bx,cx jmp tp_byebye tp_down: sub bx,cx sub dx,cx cmp dx,si jae tp_byebye mov dx,si sub dx,ax mov bx,dx mov dx,si jmp tp_byebye ExtCmdsTab label word dw offset CellTrem dw offset CellVib dw offset SlideVolUp dw offset SlideVolDown dw offset SlideVolUp dw offset SlideVolDown dw 0 dw 0 dw 0 dw 0 ExtCmds proc near mov al,es:[di+WrkBuff_CurrEvent+ev_params] xor ah,ah mov dl,10 div dl add al,al xor ah,ah mov bx,ax mov ax,cs:[ExtCmdsTab+bx] or ax,ax jz ec_dont call ax ;ah=param ec_dont: ret ExtCmds endp Adlib_BD db 0 ;contents of register BDh CellTrem proc near or ah,ah jz ct_Clear or cs:[Adlib_BD],128 jmp ct_set ct_Clear: and cs:[Adlib_BD],not 128 ct_set: mov ah,cs:[Adlib_BD] mov al,0BDh call Adlib_OUT ret CellTrem endp CellVib proc near or ah,ah jz cv_Clear or cs:[Adlib_BD],64 jmp ct_set cv_Clear: and cs:[Adlib_BD],not 64 cv_set: jmp ct_set CellVib endp SlideVolUp proc near mov bh,es:[di+WrkBuff_LastEvent+ev_vol+bp] mov al,es:[di+WrkBuff_LastEvent+ev_params+bp] xor ah,ah mov bl,10 div bl add bh,ah cmp bh,63 jbe sv_done mov bh,63 sv_done: mov es:[di+WrkBuff_LastEvent+ev_vol+bp],bh sv_hallo: call SetChannelVol ret SlideVolUp endp SlideVolDown proc near mov bh,es:[di+WrkBuff_LastEvent+ev_vol+bp] mov al,es:[di+WrkBuff_LastEvent+ev_params+bp] xor ah,ah mov bl,10 div bl sub bh,ah jns sd_done xor bh,bh sd_done: mov es:[di+WrkBuff_LastEvent+ev_vol+bp],bh call SetChannelVol ret SlideVolDown endp breakstate db 0 breakline db 0 breakptn db 0 PtnBreak proc near mov al,es:[di+WrkBuff_CurrEvent+ev_params] and al,3Fh mov cs:[breakline],al mov al,byte ptr es:[di+WrkBuff_CurrPtn] inc al mov cs:[breakptn],al mov cs:[breakstate],1 ret PtnBreak endp JumpPattern proc near mov al,es:[di+WrkBuff_CurrEvent+ev_params] mov cs:[breakptn],al mov cs:[breakline],0 mov cs:[breakstate],1 ret JumpPattern endp CmdPtrTab2 dw offset Arpeggio dw offset SlideFreqUp dw offset SlideFreqDown dw 0 dw 0 dw 0 dw 0 dw 0 dw offset TonePortamento dw offset ExtCmds2 dw 0 dw 0 dw 0 dw 0 dw 0 dw 0 ;###### Commands Type#2 ####### ; ;ah = Parameter of the Command ;es:[bp] = LastEvent Arpeggio: mov al,ah and ax,07Fh jz arp_OFF mov bl,10 div bl mov bh,byte ptr es:[di+WrkBuff_LastEvent+ev_arpeggio+bp] mov bl,bh inc bl cmp bl,3 jb arp_goon xor bl,bl arp_goon: mov byte ptr es:[di+WrkBuff_LastEvent+ev_arpeggio+bp],bl cmp bh,1 jz arp_PlayFirst cmp bh,2 jz arp_PlaySecond arp_PlayNormal: mov al,byte ptr es:[di+WrkBuff_LastEvent+ev_pitch+bp] jmp ActualPitch arp_PlayFirst: add al,byte ptr es:[di+WrkBuff_LastEvent+ev_pitch+bp] jmp ActualPitch arp_PlaySecond: mov al,byte ptr es:[di+WrkBuff_LastEvent+ev_pitch+bp] add al,ah ActualPitch: ;Play the Arpeggio!!! mov dh,byte ptr es:[di+WrkBuff_LastEvent+ev_oct+bp] cmp al,12 jbe arp_PitchOK sub al,12 inc ah arp_PitchOK: cmp dh,8 jb arp_OctOK mov dh,7 mov al,12 arp_OctOK: mov bl,dl call GetFreq add ax,word ptr es:[di+WrkBuff_LastEvent+ev_pitching+bp] mov bl,cl call SetFreq arp_OFF: ret ExtCmdsTab2 label word dw 0 dw 0 dw offset SlideVolUp dw offset SlideVolDown dw 0 dw 0 dw 0 dw 0 dw 0 dw 0 ExtCmds2 proc near mov al,es:[di+WrkBuff_LastEvent+ev_params+bp] xor ah,ah mov dl,10 div dl add al,al xor ah,ah mov bx,ax mov ax,cs:[ExtCmdsTab2+bx] or ax,ax jz ec2_dont call ax ;ah=param ec2_dont: ret ExtCmds2 endp ;al=note ;dh=octave ;->ax is absolute freq GetFreq proc near push si cx dec al add al,al xor ah,ah mov si,ax mov cx,cs:[FreqParams+si] sub cx,FreqStart mov al,dh and ax,7 mov dx,FreqRange mul dx add ax,cx pop cx si ret GetFreq endp ;ax=absolute freq ;bl=channel SetFreq proc near or ax,ax jns short sf_ok xor ax,ax sf_ok: cmp ax,FreqRange*7+305 jb sf_ok2 mov ax,FreqRange*7+305 sf_ok2: push si cx mov cx,FreqRange xor dx,dx div cx ; extracts octave in AX and freq. in DX add dx,FreqStart mov cl,al mov al,0A0h add al,bl mov ah,dl call Adlib_OUT mov al,0B0h add al,bl mov ah,cl add ah,ah add ah,ah or ah,dh or ah,100000b call Adlib_OUT pop cx si ret SetFreq endp ;al=register ;ah=value ; Adlib_OUT proc near push ax dx mov dx,388h out dx,al rept 6 in al,dx endm inc dl mov al,ah out dx,al dec dl rept 22 in al,dx endm pop dx ax ret Adlib_OUT endp ;Plays the current event ; ;es:[di+WrkBuff_CurrEvent ;cl=Channel ; PlayNote proc near push bp mov bx,cx ;--- get the pointer to current instrument in ds:bp ! mov al,byte ptr es:[di+WrkBuff_CurrEvent+ev_sam] xor ah,ah mov bp,ax dec bp js pn_Abort imul bp,34 lea bp,[bp+si+30h+23] mov al,ds:[bp+1] and al,03Fh mov es:[di+WrkBuff_ModVol+bx],al mov al,ds:[bp+6] and al,03Fh mov es:[di+WrkBuff_CarrVol+bx],al cmp byte ptr es:[di+WrkBuff_CurrEvent+ev_cmd],3 jnz pn_DontManipulate call SetCarrModVol pn_DontManipulate: mov al,cs:[ChannelOffs+bx] mov dl,4 pn_Loop: mov ah,ds:[bp] call Adlib_OUT add al,3 mov ah,ds:[bp+5] call Adlib_OUT add al,20h-3 inc bp dec dl jnz pn_Loop add al,40h ; do E0 range now mov ah,ds:[bp] call Adlib_OUT add al,3 mov ah,ds:[bp+5] call Adlib_OUT call SetChannelVol mov al,0C0h add al,bl mov ah,ds:[bp+6] call Adlib_OUT mov al,es:[di+WrkBuff_CurrEvent+ev_pitch] xor ah,ah dec ax add ax,ax mov bp,ax mov dx,cs:[FreqParams+bp] mov al,0A0h add al,bl mov ah,dl call Adlib_OUT mov al,0B0h add al,bl mov ah,dh call Adlib_OUT mov dl,es:[di+WrkBuff_CurrEvent+ev_oct] add dl,dl add dl,dl or ah,dl or ah,100000b call Adlib_OUT ;...und mit neuen Daten anschalten pn_Abort: pop bp ret PlayNote endp ChannelOffs db 20h,21h,22h,28h,29h,2ah,30h,31h,32h VolTab db 0,95/31,182/31,262/31,336/31,405/31,470/31,530/31,587/31,641/31 db 693/31,741/31,788/31,832/31,875/31,916/31,955/31,993/31,1029/31 db 1064/31,1098/31,1131/31,1163/31,1193/31,1223/31,1252/31,1280/31 db 1308/31,1335/31,1360/31,1386/31,1410/31,1435/31,1458/31,1481/31 db 1504/31,1526/31,1547/31,1568/31,1589/31,1609/31,1629/31,1648/31 db 1667/31,1686/31,1704/31,1722/31,1740/31,1757/31,1774/31,1791/31 db 1808/31,1824/31,1840/31 db 1856/31,1871/31,1887/31,1902/31,1916/31,1931/31,1945/31,1960/31 db 1974/31,1980/31 ;Sets the lastvol of channel cl ; SetChannelVol proc near pusha ;--- get the pointer to current instrument in ds:bp ! imul bx,cx,LastEventSize mov al,byte ptr es:[di+WrkBuff_LastEvent+ev_sam+bx] xor ah,ah mov bp,ax dec bp js scv_Dont imul bp,34 lea bp,[bp+si+30h+23] mov bl,byte ptr es:[di+WrkBuff_LastEvent+ev_vol+bx] xor bh,bh mov dl,cs:[VolTab+bx] mov bx,cx mov dh,cs:[ChannelOffs+bx] add dh,20h mov ah,dl xor ah,3Fh mov al,byte ptr es:[di+WrkBuff_CarrVol+bx] and al,3Fh add ah,al cmp ah,3Fh jbe scv_OK2 mov ah,3Fh scv_OK2: mov al,byte ptr ds:[bp+6] ;Carrier and al,not 3Fh or ah,al mov al,dh add al,3 call Adlib_OUT test byte ptr ds:[bp+10],1 jz scv_Serial scv_Parallel: ;Connection is ON!!! mov ah,dl xor ah,3Fh mov al,byte ptr es:[di+WrkBuff_ModVol+bx] and al,3Fh add ah,al cmp ah,3Fh jbe scv_OK mov ah,3Fh scv_OK: mov al,byte ptr ds:[bp+1] ;Mod and al,not 3Fh or ah,al mov al,dh call Adlib_OUT jmp scv_Dont scv_Serial: ;Connection is OFF!!! mov ah,byte ptr ds:[bp+1] ;Mod and ah,not 3Fh or ah,byte ptr es:[di+WrkBuff_ModVol+bx] mov al,dh call Adlib_OUT scv_Dont: popa ret SetChannelVol endp WorkBuffer db 522h dup(?)