model large,pascal .DATA noeffect EQU dw offset checkonlyPara ; no effect noeffect2 EQU dw offset handlenothing ; nothing to do for this effect here ... INCLUDE GENERAL.DEF EXTRN ORDER : BYTE EXTRN CHANNEL : TCHANNEL EXTRN PATTERN : WORD EXTRN INSTRUMENTs : WORD EXTRN usedchannels : BYTE EXTRN curline : BYTE EXTRN curOrder : BYTE EXTRN curPattern : BYTE EXTRN curtick : BYTE EXTRN curspeed : BYTE EXTRN Userate : WORD EXTRN loopS3M : BYTE EXTRN lastorder : BYTE EXTRN EndOfSong : BYTE EXTRN gvolume : BYTE EXTRN amigalimits : BYTE EXTRN sinuswave : BYTE EXTRN rampwave : BYTE EXTRN Squarewave : BYTE EXTRN Insnum : WORD EXTRN patterndelay : BYTE EXTRN Ploop_on : BYTE EXTRN Ploop_no : BYTE EXTRN Ploop_to : BYTE EXTRN patEMShandle : WORD EXTRN FrameSeg : WORD EXTRN patlength : WORD wavetab DW offset sinuswave DW offset rampwave DW offset squarewave ; looks not like a square but anyway ; 'random wave' is not a table, but a call for a random number ! st3periods dw 1712,1616,1524,1440,1356,1280,1208,1140,1076,1016, 960, 907 ; we have to init all the effects : initeffects noeffect dw offset setspeed ; effect 'A' ok ! dw offset jump2order ; effect 'B' ok ! dw offset patternbreak2 ; effect 'C' ok ! dw offset VolumeEfcts ; effect 'D' ok ! dw offset Pitchdowns ; effect 'E' ok ! dw offset Pitchups ; effect 'F' ok ! dw offset Portamento ; effect 'G' ok ! dw offset vibrato ; effect 'H' ok ! dw offset Tremor ; effect 'I' <- shity can't get it :( ... ugly implementation dw offset Arpeggio ; effect 'J' ok ! dw offset Vib_Vol ; effect 'K' ok ! dw offset Port_Vol ; effect 'L' ok ! noeffect noeffect noeffect noeffect dw offset Retrigg ; effect 'Q' ok ! dw offset Tremolo ; effect 'R' ok ! dw offset Specialsets ; effect 'S' look at special 1 dw offset setTempo ; effect 'T' ok ! dw offset vibrato ; effect 'U' ok ! (here equal to vibrato) dw offset globalvolume ; effect 'V' ok ! ; Ok now some tables for multichoise effects (e.g. 'Syx' but also 'Dxy',E,F) ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ special1 noeffect ; S0? - nothin noeffect ; set filter -> not implemented (by ST3) noeffect ; set glissando -> not implemented (by ST3) noeffect ; set finetune -> not here ! look special2 dw offset setvibwav ;OK ! dw offset settremwav ;OK ! noeffect ; does not exist noeffect ; does not exist noeffect ; maybe later (it's E8x - panning ) noeffect ; does not exist noeffect ; stereo control not implemented dw offset cmdPatloop ; dw offset InitNotecut ; dw offset InitNotedelay ; dw offset InitPatdelay ; noeffect ; funkrepeat -> not implemented retrig_dif dw offset nosld ; all done ... dw offset slddown dw offset slddown dw offset slddown dw offset slddown dw offset slddown dw offset use2div3 dw offset use1div2 dw offset nosld dw offset sldup dw offset sldup dw offset sldup dw offset sldup dw offset sldup dw offset use3div2 dw offset use2times ; and some effects we have to handle after reading vol/inst/note ; maybe refresh etc. - remember MODplayer ... ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ handleeffects noeffect2 ; really no effect ;) noeffect2 noeffect2 noeffect2 dw offset Hdl_Volfx ; effect 'D' ok! dw offset Hdl_pitchdwn ; effect 'E' ok! dw offset Hdl_pitchup ; effect 'F' ok! dw offset Hdl_porta ; effect 'G' ok! dw offset Hdl_Vibrato ; effect 'H' ok! noeffect2 dw offset Hdl_arpeggio ; effect 'J' ok! dw offset hdl_Vib_Vol ; effect 'K' ok! dw offset Hdl_Port_Vol ; effect 'L' ok! noeffect2 noeffect2 dw offset Hdl_setsmpofs ; effect 'O' ok! noeffect2 noeffect2 dw offset Hdl_tremolo ; effect 'R' ok! dw offset Hdl_Special ; effect 'S' look at special 2 noeffect2 dw offset Hdl_Vibrato ; effect 'U' ok! (here equal to vibrato noeffect2 ; Ok now some tables for multichoise effects (e.g. 'Syx' but also 'Dxy',E,F) ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Vol_cmd2nd noeffect2 noeffect2 dw offset FineVSlideDwn dw offset FineVSlideUp Pitdwn_cmd2nd noeffect2 dw offset Finepitch_down dw offset XFinepitch_down Pitup_cmd2nd noeffect2 dw offset Finepitch_up dw offset XFinepitch_up special2 noeffect2 ; S0? - nothin noeffect2 ; set filter -> not implemented (by ST3) noeffect2 ; set glissando -> not implemented (by ST3) dw offset Hdl_finetune noeffect2 ; not here -> special 1 noeffect2 ; not here -> special 1 noeffect2 ; does not exist noeffect2 ; does not exist noeffect2 ; not here -> special 1 noeffect2 ; does not exist noeffect2 ; stereo control -> not implemented (by ST3) noeffect2 ; not here -> special 1 noeffect2 ; not here -> special 1 noeffect2 ; not here -> special 1 dw offset Hdl_patterndly noeffect2 ; funkrepeat -> not implemented chnCounter db ? jump2flag db ? jump2where db ? breakflag db ? break2where db ? pLoop_now db ? gvolFlag db ? newgvol db ? ; to save portamento values : portaFlag db ? Period_old dw ? sStep_old dd ? ; a little one for arpeggio : arp_chg db ? ; save effect,parameter for patterndelay sav_cmd dw ? sav_para db ? ; now some variables I added after I found out those amazing things ; about patterndelay inpatterndly db ? ;<- call 'readnotes' inside a patterndelay, if then ignore all ;notes/inst/vol ! curnote db ? ;<- normaly it will be a copie of es:[di], but in ; patterndelay =0 <- ignore note =) curinst db ? ; the same thing for instrument curVol db ? ; and for volume ENDS .CODE .386 PUBLIC READNEWNOTES PUBLIC SetupNewInst PUBLIC SetNewNote EXTRN SET_TEMPO EXTRN EMSMAP : FAR ; <- somehow that does not work (assembler creats: ; "push cs" + "near call", but that's wrong !!! CalcFrequStep MACRO ; IN: ax = period ; OUT: destroys EDX,EBX and eax,0ffffh ; clear upper 16bit xor edx,edx mov dx,[Userate] mul edx ; EAX = Userate*Period mov ebx,eax xor edx,edx mov dx,0dah mov eax,77900000h ; EDX:EAX = 1712*8363*10000h div ebx ; 1712 * 8363 * 10000h ; EAX = ---------------------- ; Userate * Period ENDM CalcPeriod macro local notbelow,notabove ; IN: AL - Note (higher 4=name,lower 4=octave) ; FS - Segment of instrument ; OUT: AX = Period ; DESTROYs: BX,CL ; calc speriod (with st3 finetune) : mov bl,al mov cl,al shr cl,4 xor bh,bh and bl,0fh shl bl,1 ; ok calculate the period mov ax,[st3periods+bx] shl ax,4 ; period(note)*16 shr ax,cl ; period(note)*16 >> octave(note) mov dx,8363 mul dx ; dx:ax = 8363*period(note)*16 >> octave(note) mov bx,fs:[TInstrument.c2speed] div bx ; 8363*(period(note)*16 shr octave(note)) ; ax = -------------------------------------- ; C2Speed of current Sample ; Now check borders : cmp ax,[channel.lower_border+si] jnb notbelow mov ax,[channel.lower_border+si] notbelow: cmp ax,[channel.upper_border+si] jna notabove mov ax,[channel.upper_border+si] notabove: endM CheckPara0 MACRO local cp cmp al,0 jnz cp mov al,[channel.parameter+si] cp: mov [channel.parameter+si],al ENDM CheckPara0not MACRO local cp cmp al,0 je cp mov [channel.parameter+si],al cp: ENDM SetupNewInst PROC NEAR ; IN : AL = number of new instrument ; SI = offset to channel ; DS = Dataseg ; ; DESTROYs FS,BX,AX,DX ; dec al mov bl,al xor bh,bh shl bx,2 xor ah,ah add bx,ax mov ax,ds:[Instruments+2] add bx,ax mov fs,bx mov [channel.instrSEG+si],bx mov al,fs:[TInstrument.vol] cmp al,64 jb volwell mov al,63 volwell: mul [gvolume] shr ax,6 mov [channel.SampleVol+si],al mov ax,fs:[TInstrument.memseg] mov [channel.sampleSEG+si],ax mov al,fs:[TInstrument.flags] and al,00000001b ; bit 0 - loop sample ? mov [channel.sLoopflag+si],al mov ax,fs:[TInstrument.loopbeg] mov [channel.sLoopstart+si],ax mov ax,fs:[TInstrument.loopend] cmp [channel.sLoopflag+si],1 je weloop ; =:) mov ax,fs:[TInstrument.slength] ; <- we don't loop :( anyway ... weLoop: mov [channel.sLoopend+si],ax ; calc period borders mov bx,fs:[TInstrument.c2speed] cmp bx,0 jne c2speedok ; c2speed = 0 -> don't play it !! it's wrong ! mov [channel.InstrNo+si],0 c2speedok: mov [channel.ssmpstart+si],0 ; reset start value cmp [amigalimits],1 je takeamigalimits ; B-7 : mov ax,907 * 16 / 128 ; period(note)*16 >> 7 mov dx,8363 mul dx ; dx:ax = 8363*period(note)*16 >> octave(note) div bx mov [channel.lower_border+si],ax ; C-0 : mov ax,1712 * 16 ; period(note)*16 >> 0 mov dx,8363 mul dx ; dx:ax = 8363*period(note)*16 >> octave(note) cmp bx,3500 jb c2below div bx mov [channel.upper_border+si],ax jmp after1 c2below: mov bx,3500 div bx mov [channel.upper_border+si],ax jmp after1 takeamigalimits: ; first C-3 : mov ax,1712 * 16 / 8 ; period(note)*16 >> 3 mov dx,8363 mul dx ; dx:ax = 8363*period(note)*16 >> octave(note) div bx mov [channel.upper_border+si],ax ; then B-5 : mov ax,907 * 16 / 32 ; period(note)*16 >> 5 mov dx,8363 mul dx ; dx:ax = 8363*period(note)*16 >> octave(note) div bx mov [channel.lower_border+si],ax after1: mov al,[curInst] ret ENDP SetNewNote PROC NEAR ; IN: AL = note & octave ; SI = offset to channel ; ; DESTROYs: EAX,EBX,EDX,FS,CX ; ; clear it first - just to make sure we really set it mov [channel.speriod+si],0 cmp [channel.instrNo+si],0 je after2 ; if there's no instrumnet ; set pointer to instrument push ax mov ax,[channel.instrSEG+si] mov fs,ax pop ax cmp fs:[TInstrument.Typ],1 ; only calc if instrument does exist jne after2 calcperiod mov [channel.speriod+si],ax ; now step calculations : CalcFrequStep mov [channel.sStep+si],EAX cmp [portaFlag],1 je after2 ; it's porta, do not restart ! ; restart instrument xor ebx,ebx mov bx,[channel.sSmpstart+si] shl ebx,16 mov [channel.sCurpos+si],ebx mov [channel.enabled+si],1 after2: ret ENDP ; put next notes into channels READNEWNOTES PROC NEAR mov [jump2flag],0 mov [breakflag],0 mov [gvolFlag],0 mov [Ploop_now],0 mov [inpatterndly],0 cmp [patterndelay],0 je nopatdly mov [inpatterndly],1 nopatdly: mov al,[usedchannels] mov [chnCounter],al ; get next postion in current pattern mov al,[usedchannels] mov ah,al shl al,2 add al,ah ; al = 5*[usedchannels] mov ah,[curline] mul ah ; ok that was the offset : mov di,ax ; now the segment of current pattern : xor bh,bh mov bl,[curorder] mov bl,[order+bx] cmp bl,254 jae nextorder shl bx,1 mov ax,[pattern+bx] or ax,ax jz nopatloop cmp ax,0C000h jb noEMSpattern push ax push di ; Set page number: mov ah,044h xor bx,bx mov bl,al ; bx = logical page xor al,al ; al = physical page mov dx,[patEMShandle] ; dx = handle int 67h cmp ah,0 je noemsprob mov dl,0 div dl ; <- cause a "div by 0" because EMSdriver does not work correct noemsprob: pop di pop ax ; change offset to part #(ah and 0fh) shr ax,8 and al,3fh ; bit 13-8 = partno. xor ah,ah mov dx,[patlength] mul dx ; ax = partno * pattern length add di,ax mov ax,[frameSEG] noemspattern:mov es,ax ; ES:DI - pointer to current position in current pattern xor si,si ; extra channel offset (running through the channels) chnLoop: cmp [channel.channeltyp+si],2 ja donothing ; <- for adlib channels mov [portaFlag],0 ; <- set Flag back ; ok first do read current note,inst,vol -> if in patterndelay then ignore them ! mov [curNote],0ffh mov [curInst],00h mov [curVol] ,0ffh cmp [inpatterndly],1 je ignorethem mov al,es:[di] mov [curNote],al mov al,es:[di+1] mov [curInst],al mov al,es:[di+2] mov [curVol],al ignorethem: ; read effects - it may change the read instr/note ! ; ~~~~~~~~~~~~ mov al,es:[di+3] ; read effect number xor ah,ah shl ax,1 mov [channel.continueEf+si],0 cmp ax,2*8 ; Vibrato ... je checkifcontV cmp ax,2*11 ; Vibrato Volefcs je checkifcontV cmp ax,2*21 ; fine Vibrato je checkifcontV ; -> no vibrato effect, so check if last row there was one ... ; if there was - do refresh sStep cmp [channel.command+si],2*8 ; was vibrato je Vibend cmp [channel.command+si],2*21 ; was fine vibrato je Vibend cmp [channel.command+si],2*11 ; was vibrato+volef jne noVibend ; refresh frequency vibend: push ax mov ax,[channel.OldPeriod+si] mov [channel.sPeriod+si],ax cmp ax,0 je novibcalc CalcFrequStep mov [channel.sStep+si],EAX novibcalc: pop ax novibend: cmp ax,2*18 ; Tremolo ... je checkifcontTrm cmp ax,2*10 ; Arpeggio ... je checkifcontA ; - currently no arpeggio, but arpeggio was last row ? ; if there was - set sStep = Step0 (refresh frequ) cmp [channel.command+si],2*10 jne noarpegend ; arpeggio ends : push ax mov eax,[channel.step0+si] mov [channel.sStep+si],eax pop ax noarpegend: cmp ax,2*17 ; Note retrigg je checkifcontRetr aftercontcheck: mov bx,[channel.command+si] mov [sav_cmd],bx ; to save it for pattern delay ... mov [channel.command+si],ax mov [channel.cmd2nd+si],0 cmp al,44 jbe noproblem mov [channel.command+si],0 xor ax,ax noproblem: mov bx,ax mov al,es:[di+4] ; read effect parameter jmp [initeffects+bx] back2reality: effectdone: ; read instrument ; ~~~~~~~~~~~~~~~ ; reinit instrument data but don't restart ! mov al,[curInst] cmp al,00 je no_newinstr ; ------------------ check if instrument does exist push ax dec al mov bl,al xor bh,bh shl bx,2 xor ah,ah add bx,ax mov ax,ds:[Instruments+2] add bx,ax mov fs,bx cmp fs:[TInstrument.typ],1 je instok pop ax xor al,al mov [curInst],al jmp no_newinstr instok: pop ax comment # cmp [channel.enabled+si],0 ; if channel is disabled then restart definitly je restart cmp [channel.InstrNo+si],al ; but if it's enabled & same instrno then don't restart je dontrestart restart: cmp [portaFlag],1 ; and if portamento then don't restart ;) je dontrestart mov bx,[channel.sSmpstart+si] mov [channel.sCurpos+si],bx dontrestart: # mov [channel.InstrNo+si],al call near ptr SetupNewInst no_newinstr: ; read note ... ; ~~~~~~~~~~~~~ mov al,[curNote] cmp al,0ffh je no_newnote cmp al,0feh jne normal_note mov [channel.enabled+si],0 ; stop mixing jmp no_newnote normal_note: mov [channel.Note+si],al call near ptr SetNewNote no_newnote: ; read volume - last but not least ;) ; ~~~~~~~~~~~ mov al,[curVol] cmp al,0ffh je no_vol cmp al,64 jb volok mov al,63 volok: mul [gvolume] shr ax,6 mov [channel.SampleVol+si],al no_vol: ; ok now the effect handling after reading vol/instr/note mov bx,[channel.command+si] jmp [handleeffects+bx] handlenothing: donothing: add di,5 ; to next channel in pattern add si,size Channel ; to next channel in channel mix info dec [chnCounter] ; one channel done jnz chnLoop cmp [gvolFlag],0 je nonewglobal mov al,[newgvol] mov [gvolume],al nonewglobal: mov al,[curspeed] mov [curtick],al cmp [breakflag],1 je patternbreak cmp [jump2flag],1 je jumporder cmp [Ploop_now],1 je dopatloop nopatloop: inc [curline] cmp [curline],64 jne only_next ; ok - next order ... mov [curline],0 nextorder: inc [curorder] otherorder: mov [Ploop_to],0 mov al,[lastorder] cmp [curorder],al ja end_reached doloop: xor bh,bh mov bl,[curorder] mov al,[Order+bx] cmp al,254 jae nextorder mov [curpattern],al only_next: ret patternbreak:mov al,[break2where] mov [curline],al jmp nextorder jumporder: mov [curline],0 mov al,[jump2where] mov [curorder],al jmp otherorder dopatloop: dec [Ploop_no] jz patloopends mov al,[Ploop_to] mov [curline],al jmp only_next patloopends: mov al,[curline] inc al mov [PLoop_to],al mov [Ploop_on],0 jmp nopatloop end_reached: cmp [loopS3M],1 jne donotloop mov [curorder],0 jmp doloop donotloop: mov [EndOfSong],1 jmp only_next checkifcontV: ; check if continue Vib/Vib_vol cmp [curNote],0feh jb aftercontcheck cmp [channel.command+si],11*2 ; command before was vibrato je checkok1 cmp [channel.command+si],21*2 ; command before was fine vibrato je checkok1 cmp [channel.command+si],8*2 ; command before was vibrato+volef jne aftercontcheck checkok1: mov [channel.continueEf+si],1 jmp aftercontcheck checkifcontA: ; check if continue Arpeg cmp [curNote],0feh jb aftercontcheck checkifcontTrm: ; check if continue a tremolo checkifcontRetr: ; check if continue a note retrig cmp [channel.command+si],ax jne aftercontcheck mov [channel.continueEf+si],1 jmp aftercontcheck ; Effects : ; ~~~~~~~~~ checkonlyPara: checkPara0 jmp back2reality setspeed: ; effect 'A' checkPara0not cmp al,0 ; speed = 0 does not exist je back2reality mov [curspeed],al jmp back2reality jump2order: ; effect 'B' checkPara0not mov [jump2flag],1 mov [jump2where],al jmp back2reality patternbreak2: ; effect 'C' checkPara0not mov [breakflag],1 mov ah,al and al,0fh shr ah,4 AAD mov [break2where],al jmp back2reality VolumeEfcts: ; effect 'D' or jump from dual commands ... checkPara0 mov ah,al shr ah,4 cmp ah,0fh jne nofinevoldown cmp al,0f0h je volup ; normal fine volume down DFx mov [channel.cmd2nd + si],04 jmp back2reality nofinevoldown: mov ah,al and ah,0fh cmp ah,0fh jne nofinevolup cmp al,0fh je voldown ; normal fine volume up DxF mov [channel.cmd2nd + si],06 jmp back2reality nofinevolup: mov ah,al and ah,00fh jz notVslidedown ; normale slide down effect D0x voldown: mov [channel.cmd2nd + si],00 jmp back2reality notVslidedown: ; normal slide up effect Dx0 volup: mov [channel.cmd2nd + si],02 jmp back2reality Pitchdowns: ; effect 'E' checkPara0 cmp al,0DFh ; al is parameter ja extraptdowns mov [channel.cmd2nd + si],00 jmp back2reality extraptdowns: cmp al,0EFh ja Finepitchdown ; extra fine slides mov [channel.cmd2nd + si],04 jmp back2reality Finepitchdown: mov [channel.cmd2nd + si],02 jmp back2reality Pitchups: ; effect 'F' checkPara0 cmp al,0DFh ; al is parameter ja extraptups mov [channel.cmd2nd + si],00 jmp back2reality extraptups: cmp al,0EFh ja Finepitchup ; extra fine slides mov [channel.cmd2nd + si],04 jmp back2reality Finepitchup: mov [channel.cmd2nd + si],02 jmp back2reality Portamento: ; effect 'G' checkPara0not cmp al,0 je nonewPortpara mov [channel.PortPara+si],al nonewPortpara: mov [portaFlag],1 ; check first if portamento really possible: cmp [channel.enabled+si],0 je stopporta cmp [curNote],0feh jae back2reality ; <- continue portamento ; now save some values (we wanna slide from ...) mov eax,[channel.sStep+si] mov [sStep_old],eax mov ax,[channel.sPeriod+si] mov [Period_old],ax jmp back2reality stopporta: mov [channel.command+si],0 ;<-noeffect mov [portaFlag],0 jmp back2reality Vibrato: ; effect 'H' checkpara0not cmp [channel.continueEf+si],1 je norestart mov [channel.Tablepos+si],0 norestart: cmp al,0 jne newVibvalue mov al,[channel.VibPara+si] newVibValue: mov ah,al shr ah,4 cmp ah,0 jne Vibspeedok mov ah,[channel.VibPara+si] and ah,0f0h or al,ah VibspeedOk: mov [channel.VibPara+si],al jmp back2reality Tremor: ; effect 'I' checkPara0 jmp back2reality Arpeggio: ; effect 'J' cmp al,0 je uselastPara mov [arp_chg],1 mov [channel.parameter+si],al jmp back2reality uselastPara: mov [arp_chg],0 jmp back2reality Vib_Vol: ; effect 'K' cmp [channel.continueEf+si],1 je volumeefcts mov [channel.Tablepos+si],0 jmp volumeefcts Port_Vol: ; effect 'L' mov [portaFlag],1 ; check first if portamento really possible: cmp [channel.enabled+si],0 je stopporta ; <- channel plays nothing -> no porta and volfx usefull ;) cmp [curNote],0feh jae volumeefcts ; <- continue portamento ; now save some values (we wanna slide from ...) push ax mov eax,[channel.sStep+si] mov [sStep_old],eax mov ax,[channel.sPeriod+si] mov [Period_old],ax pop ax jmp volumeefcts ; <- and now volume effects Retrigg: ; effect 'Q' cmp al,0 jne newretrPara mov al,[channel.parameter+si] jmp aftersetretr newretrPara: mov [channel.parameter+si],al mov ah,al and ah,0fh cmp ah,0 je noretrigg dec ah mov [channel.ctick+si],ah aftersetretr: mov bl,al shr bl,4 shl bl,1 xor bh,bh jmp [retrig_dif+bx] nosld: mov [channel.cmd2nd+si],0 jmp back2reality slddown: mov [channel.cmd2nd+si],2 jmp back2reality use2div3: mov [channel.cmd2nd+si],4 jmp back2reality use1div2: mov [channel.cmd2nd+si],6 jmp back2reality sldup: mov [channel.cmd2nd+si],8 jmp back2reality use3div2: mov [channel.cmd2nd+si],10 jmp back2reality use2times: mov [channel.cmd2nd+si],12 jmp back2reality noretrigg: mov [channel.command+si],0 jmp back2reality Tremolo: ; effect 'R' cmp [channel.continueEf+si],1 je noTrmrestart mov [channel.Tablepos+si],0 noTrmrestart: cmp al,0 jne newTrmvalue mov al,[channel.Parameter+si] newTrmValue: mov ah,al shr ah,4 cmp ah,0 jne Trmspeedok mov ah,[channel.Parameter+si] and ah,0f0h or al,ah TrmspeedOk: mov [channel.Parameter+si],al jmp back2reality Specialsets: ; effect 'S' checkPara0 xor bh,bh mov bl,al shr bl,4 shl bx,1 mov [channel.cmd2nd+si],bx ; do effects we have to check before reading note/vol/instr jmp [special1+bx] setvibwav: ; for every channel a seperate choise ! and al,3 add al,al xor ah,ah mov bx,ax shl bx,1 mov ax,[wavetab+bx] mov [channel.VibTabOfs+si],ax jmp back2reality settremwav: ; for every channel a seperate choise ! and al,3 add al,al xor ah,ah mov bx,ax shl bx,1 mov ax,[wavetab+bx] mov [channel.TrmTabOfs+si],ax jmp back2reality cmdPatloop: and al,0fh cmp al,0 je set2where cmp [Ploop_on],1 je alreadyinside mov [Ploop_on],1 inc al mov [Ploop_no],al alreadyinside: mov [Ploop_now],1 jmp back2reality set2where: mov al,[curline] mov [Ploop_to],al jmp back2reality InitNotecut: and al,0fh cmp al,0 je noCut ;inc al mov [channel.ndtick+si],al jmp back2reality noCut: mov [channel.command+si],9 jmp back2reality InitNotedelay: and al,0fh mov [channel.ndTick+si],al cmp [inpatterndly],1 je donothing mov al,[curNote] ; new note for later mov [channel.savnote+si],al mov al,[curInst] ; new instrument for later mov [channel.savInst+si],al mov al,[curVol] ; new volume for later mov [channel.savVol+si],al jmp donothing ; setup note/instr/vol later while mixing ! InitPatdelay: cmp [inpatterndly],1 je back2reality ; <- hehe we are allread in this patterndelay ... and al,0fh inc al mov [patterndelay],al mov al,[channel.parameter+si] mov [sav_para],al jmp back2reality setTempo: ; effect 'T' checkPara0not xor ah,ah push si di fs es push ax call far ptr SET_TEMPO pop es fs di si jmp back2reality globalvolume: ; effect 'V' checkPara0not mov [gvolFlag],1 cmp al,64 jbe gvolok mov al,64 gvolok: mov [newgvol],al jmp back2reality ; _____________________________________ ; Effect after reading vol/instr/note : ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Hdl_Volfx: ; effect 'D' mov bx,[channel.cmd2nd + si] jmp [vol_cmd2nd+bx] FineVSlideDwn:mov al,[channel.Parameter+si] and al,0fh sub [channel.SampleVol+si],al jnc handlenothing mov [channel.SampleVol+si],0 jmp handlenothing FineVSlideUp: mov al,[channel.Parameter+si] shr al,4 add [channel.SampleVol+si],al cmp [channel.SampleVol+si],64 jb handlenothing mov [channel.SampleVol+si],63 jmp handlenothing Hdl_pitchdwn: ; effect 'E' mov bx,[channel.cmd2nd + si] jmp [pitdwn_cmd2nd+bx] Finepitch_down: ; we pitch down, but increase period ! (so check upper_border) mov ax,[channel.sPeriod+si] mov bl,[channel.Parameter+si] and bl,0fh xor bh,bh shl bx,2 add ax,bx cmp ax,[channel.upper_border+si] jb ptok mov ax,[channel.upper_border+si] ptok: ; now calc new frequency step for this period mov [channel.sPeriod+si],ax CalcFrequStep mov ds:[channel.sStep+si],EAX jmp handlenothing XFinepitch_down: ; we pitch down, but increase period ! (so check upper_border) mov ax,[channel.sPeriod+si] mov bl,[channel.Parameter+si] and bl,0fh xor bh,bh add ax,bx cmp ax,[channel.upper_border+si] jb ptok mov ax,[channel.upper_border+si] jmp ptok Hdl_pitchup: ; effect 'F' mov bx,[channel.cmd2nd + si] jmp [pitup_cmd2nd+bx] Finepitch_up: ; we pitch up, but decrease period ! (so check lower_border) mov ax,[channel.sPeriod+si] mov bl,[channel.Parameter+si] and bl,0fh xor bh,bh shl bx,2 sub ax,bx cmp ax,[channel.lower_border+si] ja ptok mov ax,[channel.lower_border+si] jmp ptok XFinepitch_up:; we pitch up, but decrease period ! (so check lower_border) mov ax,[channel.sPeriod+si] mov bl,[channel.Parameter+si] and bl,0fh xor bh,bh sub ax,bx cmp ax,[channel.lower_border+si] ja ptok mov ax,[channel.lower_border+si] jmp ptok Hdl_porta: ; effect 'G' cmp [curNote],0feh jae handlenothing ; <- is a portamento continue mov ax,[Period_Old] xchg ax,[channel.sPeriod+si] mov [channel.wantedPeri+si],ax mov eax,[sStep_old] mov [channel.sStep+si],eax jmp handlenothing Hdl_Vibrato: ; effect 'H' cmp [channel.continueEf+si],1 je handlenothing ; continue this effect ! mov ax,[channel.sPeriod+si] mov [channel.OldPeriod+si],ax jmp handlenothing Hdl_arpeggio: ; effect 'J' cmp [arp_chg],1 je newPara cmp [channel.continueEf+si],1 je handlenothing ; no new note ! ; start arpeggio: mov [channel.ArpegPos+si],0 newPara: mov al,[channel.parameter+si] mov ah,[channel.note+si] ; calc note 1: mov bl,ah mov bh,al shr bh,4 ; upper 4 bits for note 1 add bl,bh mov bh,bl and bh,0f0h and bl,00fh arpt1: cmp bl,12 jb arpok1 sub bl,12 add bh,10h jmp arpt1 arpok1: or bh,bl mov [channel.note1+si],bh ; now note 2: mov bl,ah mov bh,al and bh,0fh ; lower 4 bits for note 2 add bl,bh mov bh,bl and bh,0f0h and bl,00fh arpt2: cmp bl,12 jb arpok2 sub bl,12 add bh,10h jmp arpt2 arpok2: or bh,bl mov [channel.note2+si],bh ; now calc the Steps: mov ax,[channel.instrSEG+si] mov fs,ax mov al,[channel.Note+si] call near ptr calcpart mov [channel.Step0+si],eax mov al,[channel.Note1+si] call near ptr calcpart mov [channel.Step1+si],eax mov al,[channel.Note2+si] call near ptr calcpart mov [channel.Step2+si],eax jmp handlenothing calcpart: calcperiod cmp ax,0 je nostep calcfrequStep retn nostep: xor eax,eax retn Hdl_Vib_Vol: cmp [channel.continueEf+si],1 je Hdl_Volfx mov ax,[channel.sPeriod+si] mov [channel.OldPeriod+si],ax jmp Hdl_Volfx Hdl_Port_Vol: ; effect 'L' ; first handle Portamento (and then jump to volume effect handling) cmp [curNote],0feh jae Hdl_Volfx mov ax,[Period_Old] xchg ax,[channel.sPeriod+si] mov [channel.wantedPeri+si],ax mov eax,[sStep_old] mov [channel.sStep+si],eax jmp Hdl_Volfx Hdl_setsmpofs:; effect 'O' xor eax,eax mov ah,[channel.parameter+si] mov [channel.ssmpstart+si],ax shl eax,16 cmp [curnote],0ffh je handlenothing mov [channel.sCurPos+si],eax jmp handlenothing Hdl_tremolo: ; effect 'R' (Tremolo) cmp [curInst],0 jne savevol ; new instrument cmp [curVol],0ffh jne savevol ; new volume cmp [channel.continueEf+si],1 je handlenothing ; continue this effect ! ; save volume savevol: mov al,[channel.SampleVol+si] mov [channel.OldVolume+si],al jmp handlenothing Hdl_Special: ; effect 'S' mov bx,[channel.cmd2nd+si] jmp [special2+bx] Hdl_finetune: jmp handlenothing Hdl_patterndly: mov al,[sav_para] mov [channel.parameter+si],al mov ax,[sav_cmd] mov [channel.command+si],ax mov [channel.cmd2nd+si],0 jmp handlenothing READNEWNOTES ENDP ENDS END