home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-06-18 | 84.9 KB | 3,334 lines |
- ;============================================================================
- ; promixplayer.a
- ; ~~~~~~~~~~~~~~
- ; $VER: promixplayer 7.1 (14.6.1996)
- ;
- ; The music player routine for MMD2/MMD3 OctaMED
- ; 1-64 channel modules using the mixing mode.
- ;
- ; Copyright © 1995-1996 Teijo Kinnunen and RBF Software.
- ;
- ; Written by Teijo Kinnunen.
- ; Technical comments/questions/bug reports can be sent to:
- ; Teijo Kinnunen
- ; Oksantie 19
- ; FIN-86300 OULAINEN
- ; FINLAND
- ; email: Teijo.Kinnunen@oulu.fi
- ;
- ; See OctaMED docs for conditions about using these routines.
- ; Comments/questions about distribution and usage conditions
- ; should be directed to RBF Software.
- ;
- ; (Email: rbfsoft@octamed.co.uk or rbfsoft@cix.compulink.co.uk)
- ;
- ;============================================================================
-
- ;****** Feature control ******
- ;
- MIDI EQU 0 ;1 = include MIDI code
- AUDDEV EQU 1 ;1 = allocate channels using audio.device
- SYNTH EQU 1 ;1 = include synth-sound handler
- CHECK EQU 1 ;1 = do range checkings (track, sample in mem etc.)
- RELVOL EQU 1 ;1 = include relative volume handling code
- HOLD EQU 1 ;1 = handle hold/decay
- ;
- ; The less features you include, the faster and shorter the play-routine
- ; will be.
- ;
-
- ;============================================================================
-
- INCLUDE "chinfo.i"
-
- ; The MMD structure offsets
- mmd_id EQU 0
- mmd_modlen EQU 4
- mmd_songinfo EQU 8
- ; these two for MMD2s only!
- mmd_psecnum EQU 12
- mmd_pseq EQU 14
- ;
- mmd_blockarr EQU 16
- mmd_smplarr EQU 24
- mmd_expdata EQU 32
- mmd_pstate EQU 40 ; <0 = play song, 0 = don't play, >0 = play block
- mmd_pblock EQU 42
- mmd_pline EQU 44
- mmd_pseqnum EQU 46
- mmd_counter EQU 50
- mmd_songsleft EQU 51
-
- INCLUDE "medtrkdata.i"
-
- ; Instrument data
- inst_repeat EQU 0
- inst_replen EQU 2
- inst_midich EQU 4
- inst_midipreset EQU 5
- inst_svol EQU 6
- inst_strans EQU 7
-
- ; Audio hardware offsets
- ac_ptr EQU $00
- ac_len EQU $04
- ac_per EQU $06
- ac_vol EQU $08
-
- AUDIO_CONST EQU 3579545
-
- ; Maximum number of tracks allowed. If you don't need this much tracks,
- ; you can decrease the number to save some space. (Be sure that the
- ; song really has no more than MAX_NUMTRACKS tracks. Minimum allowed
- ; value = 4.)
- MAX_NUMTRACKS EQU 64
-
- ; This value is used for MMD0/1 conversion. If MAX_NUMTRACKS <= 16,
- ; this should be the same. If MAX_NUMTRACKS > 16, this should be 16.
- MAX_MMD1_TRACKS EQU 16
-
- SECTION "text",CODE
-
- ; -------- _ChannelOff: Turn off a channel -------------------------------
- _ChannelOff: ;d0 = channel #
- lea DB,a0
- lea trackdataptrs-DB(a0),a1
- lsl.w #2,d0
- adda.w d0,a1
- lsr.w #2,d0
- movea.l (a1),a1
- move.b trk_outputdev(a1),d1
- bne.s choff_exit
- IFNE MIDI
- move.b trk_prevmidin(a1),d1 ;first: is it MIDI??
- bne.s choff_ismidi ;not a midi note
- ENDC
- move.l d7,-(sp)
- move.w d0,d7
- movea.l a1,a5
- XREF _ChOff_mix
- jsr _ChOff_mix(pc)
- move.l (sp)+,d7
- ; -------- TURN OFF AMIGA-CHANNEL ----------------------------------------
- IFNE SYNTH
- clr.l trk_synthptr(a1)
- clr.b trk_synthtype(a1)
- ENDC
- clr.w trk_soffset(a1)
- choff_exit rts
-
- IFNE MIDI
- ; -------- TURN OFF MIDI TRACK -------------------------------------------
- choff_ismidi lea noteondata-DB(a0),a0
- choff_midi: clr.b trk_prevmidin(a1)
- move.b d1,1(a0)
- bmi.s choff_exit
- move.b trk_prevmidich(a1),(a0) ;prev midi channel
- clr.b 2(a0)
- or.b #$90,(a0) ;note off
- moveq #3,d0
- bra.w _AddMIDIData
- ENDC
-
- ; -------- SoundOff: Turn off all channels -------------------------------
- SoundOff: movem.l d2/a5,-(sp)
- moveq #MAX_NUMTRACKS-1,d2
- SO_loop0 move.l d2,d0
- bsr.s _ChannelOff
- dbf d2,SO_loop0
- clr.l _module ;play nothing
- movem.l (sp)+,d2/a5
- SO_rts rts
-
- ; -------- _PlayNote: The note playing routine ---------------------------
- _PlayNote: ;d7(w) = trk #, d1 = note #, d3(w) = instr # a3 = addr of instr
- ; -------- CHECK INSTRUMENT (existence, type) ----------------------------
- move.l a3,d4
- beq.s SO_rts
- moveq #0,d4
- bset d7,d4 ;d4 is mask for this channel
- movea.l mmd_smplarr(a2),a0
- add.w d3,d3 ;d3 = instr.num << 2
- add.w d3,d3
- move.l 0(a0,d3.w),d5 ;get address of instrument
- IFNE MIDI
- bne.s inmem
- tst.b inst_midich(a3) ;is MIDI channel set?
- ENDC
- IFNE CHECK
- beq.w pnote_rts ; NO!!!
- ENDC
- ; -------- ADD TRANSPOSE -------------------------------------------------
- inmem add.b msng_playtransp(a4),d1 ;add play transpose
- add.b inst_strans(a3),d1 ;and instr. transpose
- move.b trk_outputdev(a5),d3
- beq.s pn_offami
- bra.s noprevmidi ;dunno.. unsupported type
-
- ; -------- TURN OFF CHANNEL DMA, IF REQUIRED -----------------------------
- pn_offami cmp.w maxaudiotrk-DB(a6),d7
- bge.s nodmaoff
- move.l d5,a1
- IFNE SYNTH
- tst.l d5
- beq.s stpdma
- tst.b trk_synthtype(a5)
- ble.s stpdma ;prev. type = sample/hybrid
- cmp.w #-1,4(a1) ;type == SYNTHETIC??
- beq.s nostpdma
- ENDC
- stpdma: move.w d1,-(sp)
- XREF _MixPrepSynth
- jsr _MixPrepSynth(pc)
- move.w (sp)+,d1
- nostpdma:
- IFNE SYNTH
- clr.l trk_synthptr(a5)
- ENDC
- nodmaoff: subq.b #1,d1
- IFNE MIDI
- ; -------- KILL PREVIOUS MIDI NOTE ---------------------------------------
- move.b trk_prevmidin(a5),d3 ;get prev. midi note
- beq.s noprevmidi
- clr.b trk_prevmidin(a5)
- lea noteondata+2-DB(a6),a0
- clr.b (a0)
- move.b d3,-(a0)
- bmi.s noprevmidi
- move.b trk_prevmidich(a5),-(a0) ;prev midi channel
- or.b #$90,(a0) ;note off
- move.w d1,-(sp)
- moveq #3,d0
- bsr.w _AddMIDId
- move.w (sp)+,d1
- noprevmidi
- ; -------- IF MIDI NOTE, CALL MIDI NOTE ROUTINE --------------------------
- tst.b inst_midich(a3)
- bne.w handleMIDInote
- ENDC
- ; -------- TEST OUTPUT DEVICE AND BRANCH IF NOT STD ----------------------
- IFEQ MIDI
- noprevmidi
- ENDC
- ; -------- SET SOME AMIGA-CHANNEL PARAMETERS -----------------------------
- IFNE CHECK
- cmp.w maxaudiotrk-DB(a6),d7
- bge.w pnote_rts ;no Amiga instruments here!!!
- ENDC
- IFNE HOLD
- clr.b trk_fadespd(a5) ;no fade yet..
- move.b trk_initdecay(a5),trk_decay(a5) ;set decay
- ENDC
- clr.w trk_vibroffs(a5) ;clr vibrato/tremolo offset
- move.l d5,a0
- IFNE SYNTH
- ; -------- IF SYNTH NOTE, CALL SYNTH ROUTINE -----------------------------
- tst.w 4(a0)
- bmi.w handleSynthnote
- clr.b trk_synthtype(a5)
- ENDC
- XREF _PlayNoteMix
- pn_hybrid jsr _PlayNoteMix(pc)
- IFNE SYNTH
- tst.b trk_synthtype(a5)
- bne.w hSn2
- ENDC
- pnote_rts rts
-
- handlenonstdout
- rts
-
- IFNE MIDI
- ; -------- MIDI NOTE PLAYER ROUTINE --------------------------------------
- handleMIDInote:
- ; -------- CHECK & SCALE VOLUME ------------------------------------------
- move.b trk_prevvol(a5),d2 ;temporarily save the volume
- IFNE RELVOL
- ; -------- GetRelVol: Calculate track volume -----------------------------
- ext.w d2
- mulu trk_trackvol(a5),d2
- lsr.w #7,d2
- ENDC
- IFEQ RELVOL
- lsl.b #1,d2
- ENDC
- subq.b #1,d2 ;if 128 => 127
- bpl.s hmn_notvolu0
- moveq #0,d2
- hmn_notvolu0
- moveq #0,d5
- ; -------- CHECK MIDI CHANNEL --------------------------------------------
- move.b inst_midich(a3),d5 ;get midi chan of this instrument
- bpl.s hmn_nosmof ;bit 7 clear
- clr.b trk_prevmidin(a5) ;suppress note off!
- bra.s hmn_smof
- hmn_nosmof move.b d1,trk_prevmidin(a5)
- hmn_smof and.b #$1F,d5 ;clear all flag bits etc...
- subq.b #1,d5 ;from 1-16 to 0-15
- move.b d5,trk_prevmidich(a5) ;save to prev midi channel
-
- ; -------- CHECK MIDI PRESET ---------------------------------------------
- moveq #0,d0
- move.b trk_previnstr(a5),d0
- add.w d0,d0
- lea ext_midipsets-DB(a6),a1
- move.w 0(a1,d0.w),d0 ;get preset #
- beq.s nochgpres ;zero = no preset
- lea prevmidicpres-DB(a6),a1
- adda.w d5,a1
- adda.w d5,a1
- cmp.w (a1),d0 ;is this previous preset ??
- beq.s nochgpres ;yes...no need to change
- move.w d0,(a1) ;save preset to prevmidicpres
- subq.w #1,d0 ;sub 1 to get 0 - 127
- btst #6,inst_midich(a3)
- bne.s hmn_extpreset
- ; -------- PREPARE PRESET CHANGE COMMAND ---------------------------------
- hmn_ordpreset lea preschgdata+1-DB(a6),a0
- move.b d0,(a0) ;push the number to second byte
- moveq #2,d0
- hmn_sendpreset move.b #$c0,-(a0) ;command: $C
- or.b d5,(a0) ;"or" midi channel
- move.w d1,-(sp)
- bsr.w _AddMIDId
- move.w (sp)+,d1
- tst.b d2
- beq.s hmn_suppress ;vol = 0, don't send NOTE ON
-
- ; -------- PREPARE & SEND NOTE ON COMMAND --------------------------------
- nochgpres lea bytesinnotebuff-DB(a6),a0
- movea.l a0,a1
- adda.w (a0)+,a0
- or.b #$90,d5 ;MIDI: Note on
- move.b d5,(a0)+ ;MIDI msg Note on & channel
- move.b d1,(a0)+ ;MIDI msg note #
- move.b d2,(a0) ;MIDI msg volume
- beq.s hmn_suppress ;vol = 0 -> no note
- addq.w #3,(a1)
- rts
- hmn_suppress st trk_prevmidin(a5)
- rts
-
- ; -------- HANDLE EXTENDED PRESET ----------------------------------------
- hmn_extpreset cmp.w #100,d0
- blt.s hmn_ordpreset
- moveq #99,d3
- hmn_loop100 sub.w #100,d0
- addq.b #1,d3
- cmp.w #100,d0
- bge.s hmn_loop100
- lea preschgdata+2-DB(a6),a0
- move.b d0,(a0) ;push the <= 99 number
- move.b d3,-(a0) ;push the >= 100 number
- moveq #3,d0
- bra.s hmn_sendpreset
- ENDC
-
- IFNE SYNTH
- ; -------- TRIGGER SYNTH NOTE, CLEAR PARAMETERS --------------------------
- handleSynthnote move.b d1,trk_prevnote2(a5)
- move.l a0,trk_synthptr(a5)
- cmp.w #-2,4(a0) ;HYBRID??
- bne.s hSn_nossn
- st trk_synthtype(a5)
- movea.l 278(a0),a0 ;yep, get the waveform pointer
- bra.w pn_hybrid ;go and play it
- hSn_nossn: move.b #1,trk_synthtype(a5)
- lea _freq_tables+32-DB(a6),a1
- move.b trk_finetune(a5),d0 ;finetune value
- add.b d0,d0
- add.b d0,d0 ;multiple by 4...
- ext.w d0 ;extend
- movea.l 0(a1,d0.w),a1 ;period table address
- move.l a1,trk_periodtbl(a5) ;save table ptr for synth periods
- add.w d1,d1
- move.w 0(a1,d1.w),d1
- move.w d1,trk_prevper(a5)
- clr.l trk_sampleptr(a5)
- hSn2: lea trk_arpgoffs(a5),a1
- clr.l (a1)+
- clr.l (a1)+
- btst #0,trk_miscflags(a5)
- bne.s hSn_cmdE ;cmd E given, don't clear trk_wfcmd!
- clr.w (a1)
- hSn_cmdE addq.l #2,a1
- clr.w (a1)+
- clr.l (a1)+
- clr.l (a1)+
- clr.l (a1)+
- move.l #sinetable,(a1)+
- clr.w (a1)+
- movea.l trk_synthptr(a5),a0
- move.w 18(a0),(a1)+
- clr.b (a1)
- moveq #64,d4
- rts
-
- synth_start move.w trk_prevper(a5),d5
- synth_start2 move.l d0,a0
- ; -------- SYNTHSOUND VOLUME SEQUENCE HANDLING ---------------------------
- subq.b #1,trk_volxcnt(a5) ;decrease execute counter..
- bgt.w synth_wftbl ;not 0...go to waveform
- move.b trk_initvolxspd(a5),trk_volxcnt(a5) ;reset counter
- move.b trk_volchgspd(a5),d0 ;volume change??
- beq.s synth_nochgvol ;no.
- add.b trk_synvol(a5),d0 ;add previous volume
- bpl.s synth_voln2l ;not negative
- moveq #0,d0 ;was negative => 0
- synth_voln2l cmp.b #$40,d0 ;too high??
- ble.s synth_voln2h ;not 2 high.
- moveq #$40,d0 ;was 2 high => 64
- synth_voln2h move.b d0,trk_synvol(a5) ;remember new...
- synth_nochgvol move.l trk_envptr(a5),d1 ;envelope pointer
- beq.s synth_novolenv
- movea.l d1,a1
- move.b (a1)+,d0
- add.b #128,d0
- lsr.b #2,d0
- move.b d0,trk_synvol(a5)
- addq.b #1,trk_envcount(a5)
- bpl.s synth_endenv
- clr.b trk_envcount(a5)
- move.l trk_envrestart(a5),a1
- synth_endenv move.l a1,trk_envptr(a5)
- synth_novolenv move.w trk_volcmd(a5),d0 ;get table position ptr
- tst.b trk_volwait(a5) ;WAI(t) active
- beq.s synth_getvolcmd ;no
- subq.b #1,trk_volwait(a5) ;yep, decr wait ctr
- ble.s synth_getvolcmd ;0 => continue
- bra.w synth_wftbl ;> 0 => still wait
- synth_inccnt addq.b #1,d0
- synth_getvolcmd addq.b #1,d0 ;advance pointer
- move.b 21(a0,d0.w),d1 ;get command
- bmi.s synth_cmd ;negative = command
- move.b d1,trk_synvol(a5) ;set synthvol
- bra.w synth_endvol ;end of volume executing
- synth_cmd and.w #$000f,d1
- add.b d1,d1
- move.w synth_vtbl(pc,d1.w),d1
- jmp syv(pc,d1.w)
- synth_vtbl dc.w syv_f0-syv,syv_f1-syv,syv_f2-syv,syv_f3-syv
- dc.w syv_f4-syv,syv_f5-syv,syv_f6-syv
- dc.w synth_endvol-syv,synth_endvol-syv,synth_endvol-syv
- dc.w syv_fa-syv,syv_ff-syv,synth_endvol-syv
- dc.w synth_endvol-syv,syv_fe-syv,syv_ff-syv
- ; -------- VOLUME SEQUENCE COMMANDS --------------------------------------
- syv
- syv_fe move.b 22(a0,d0.w),d0 ;JMP
- bra.s synth_getvolcmd
- syv_f0 move.b 22(a0,d0.w),trk_initvolxspd(a5) ;change volume ex. speed
- bra.s synth_inccnt
- syv_f1 move.b 22(a0,d0.w),trk_volwait(a5) ;WAI(t)
- addq.b #1,d0
- bra.s synth_endvol
- syv_f3 move.b 22(a0,d0.w),trk_volchgspd(a5) ;set volume slide up
- bra.s synth_inccnt
- syv_f2 move.b 22(a0,d0.w),d1
- neg.b d1
- move.b d1,trk_volchgspd(a5) ;set volume slide down
- bra.s synth_inccnt
- syv_fa move.b 22(a0,d0.w),trk_wfcmd+1(a5) ;JWS (jump wform sequence)
- clr.b trk_wfwait(a5)
- bra.s synth_inccnt
- syv_f4 move.b 22(a0,d0.w),d1
- bsr.s synth_getwf
- clr.l trk_envrestart(a5)
- syv_f4end move.l a1,trk_envptr(a5)
- clr.b trk_envcount(a5)
- bra.w synth_inccnt
- syv_f5 move.b 22(a0,d0.w),d1
- bsr.s synth_getwf
- move.l a1,trk_envrestart(a5)
- bra.s syv_f4end
- syv_f6 clr.l trk_envptr(a5)
- bra.w synth_getvolcmd
- synth_getwf ext.w d1 ;d1 = wform number, returns ptr in a1
- add.w d1,d1 ;create index
- add.w d1,d1
- lea 278(a0),a1
- adda.w d1,a1
- movea.l (a1),a1 ;get wform address
- addq.l #2,a1 ;skip length
- rts
- syv_ff subq.b #1,d0
- synth_endvol move.w d0,trk_volcmd(a5)
- synth_wftbl moveq #0,d0
- move.b trk_synvol(a5),d0
- moveq #0,d1
- move.b trk_prevvol(a5),d1
- mulu d0,d1
- asr.w #6,d1
- move.b d1,trk_tempvol(a5)
- adda.w #158,a0
- ; -------- SYNTHSOUND WAVEFORM SEQUENCE HANDLING -------------------------
- subq.b #1,trk_wfxcnt(a5) ;decr. wf speed counter
- bgt.w synth_arpeggio ;not yet...
- move.b trk_initwfxspd(a5),trk_wfxcnt(a5) ;restore speed counter
- move.w trk_wfcmd(a5),d0 ;get table pos offset
- move.w trk_wfchgspd(a5),d1 ;CHU/CHD ??
- beq.s synth_tstwfwai ;0 = no change
- wytanwet add.w trk_perchg(a5),d1 ;add value to current change
- move.w d1,trk_perchg(a5) ;remember amount of change
- synth_tstwfwai tst.b trk_wfwait(a5) ;WAI ??
- beq.s synth_getwfcmd ;not waiting...
- subq.b #1,trk_wfwait(a5) ;decr wait counter
- beq.s synth_getwfcmd ;waiting finished
- bra.w synth_arpeggio ;still sleep...
- synth_incwfc addq.b #1,d0
- synth_getwfcmd addq.b #1,d0 ;advance position counter
- move.b -9(a0,d0.w),d1 ;get command
- bmi.s synth_wfcmd ;negative = command
- ext.w d1
- add.w d1,d1
- add.w d1,d1
- movea.l 120(a0,d1.w),a1
- synth_setmixwf XREF _MixSetSynthWF
- move.l d0,-(sp)
- move.l a0,-(sp)
- jsr _MixSetSynthWF(pc)
- move.l (sp)+,a0
- move.l (sp)+,d0
- bra.w synth_wfend ;no new commands now...
- synth_wfcmd and.w #$000f,d1 ;get the right nibble
- add.b d1,d1 ;* 2
- move.w synth_wfctbl(pc,d1.w),d1
- jmp syw(pc,d1.w) ;jump to command
- synth_wfctbl dc.w syw_f0-syw,syw_f1-syw,syw_f2-syw,syw_f3-syw,syw_f4-syw
- dc.w syw_f5-syw,syw_f6-syw,syw_f7-syw,synth_wfend-syw
- dc.w synth_wfend-syw,syw_fa-syw,syw_ff-syw
- dc.w syw_fc-syw,synth_getwfcmd-syw,syw_fe-syw,syw_ff-syw
- ; -------- WAVEFORM SEQUENCE COMMANDS ------------------------------------
- syw
- syw_f7 move.b -8(a0,d0.w),d1
- ext.w d1
- add.w d1,d1
- add.w d1,d1
- movea.l 120(a0,d1.w),a1
- addq.l #2,a1
- move.l a1,trk_synvibwf(a5)
- bra.s synth_incwfc
- syw_fe move.b -8(a0,d0.w),d0 ;jump (JMP)
- bra.s synth_getwfcmd
- syw_fc move.w d0,trk_arpsoffs(a5) ;new arpeggio begin
- move.w d0,trk_arpgoffs(a5)
- synth_findare addq.b #1,d0
- tst.b -9(a0,d0.w)
- bpl.s synth_findare
- bra.s synth_getwfcmd
- syw_f0 move.b -8(a0,d0.w),trk_initwfxspd(a5) ;new waveform speed
- bra synth_incwfc
- syw_f1 move.b -8(a0,d0.w),trk_wfwait(a5) ;wait waveform
- addq.b #1,d0
- bra.s synth_wfend
- syw_f4 move.b -8(a0,d0.w),trk_synvibdep+1(a5) ;set vibrato depth
- bra.w synth_incwfc
- syw_f5 move.b -8(a0,d0.w),trk_synthvibspd+1(a5) ;set vibrato speed
- addq.b #1,trk_synthvibspd+1(a5)
- bra.w synth_incwfc
- syw_f2 moveq #0,d1 ;set slide down
- move.b -8(a0,d0.w),d1
- synth_setsld move.w d1,trk_wfchgspd(a5)
- bra.w synth_incwfc
- syw_f3 move.b -8(a0,d0.w),d1 ;set slide up
- neg.b d1
- ext.w d1
- bra.s synth_setsld
- syw_f6 clr.w trk_perchg(a5) ;reset period
- move.w trk_prevper(a5),d5
- bra.w synth_getwfcmd
- syw_fa move.b -8(a0,d0.w),trk_volcmd+1(a5) ;JVS (jump volume sequence)
- clr.b trk_volwait(a5)
- bra.w synth_incwfc
- syw_ff subq.b #1,d0 ;pointer = END - 1
- synth_wfend move.w d0,trk_wfcmd(a5)
- ; -------- HANDLE SYNTHSOUND ARPEGGIO ------------------------------------
- synth_arpeggio move.w trk_arpgoffs(a5),d1
- beq.s synth_vibrato
- moveq #0,d0
- move.b -8(a0,d1.w),d0
- add.b trk_prevnote2(a5),d0
- movea.l trk_periodtbl(a5),a1 ;get period table
- add.w d0,d0
- move.w 0(a1,d0.w),d5
- addq.b #1,d1
- tst.b -8(a0,d1.w)
- bpl.s synth_noarpres
- move.w trk_arpsoffs(a5),d1
- synth_noarpres move.w d1,trk_arpgoffs(a5)
- ; -------- HANDLE SYNTHSOUND VIBRATO -------------------------------------
- synth_vibrato move.w trk_perchg(a5),d1
- tst.w trk_synvibdep(a5) ;get vibrato depth
- beq.s synth_novib ;0 => no vibrato
- move.w trk_synviboffs(a5),d0 ;get offset
- lsr.w #4,d0 ;/ 16
- and.w #$1f,d0 ;sinetable offset (0-31)
- movea.l trk_synvibwf(a5),a0
- move.b 0(a0,d0.w),d0 ;get a byte
- ext.w d0 ;to word
- muls trk_synvibdep(a5),d0 ;amplify (* depth)
- asr.w #8,d0 ;and divide by 64
- add.w d0,d1 ;add vibrato...
- move.w trk_synthvibspd(a5),d0 ;vibrato speed
- add.w d0,trk_synviboffs(a5) ;add to offset
- synth_novib tst.w d5
- beq.s synth_rtper
- move.l #AUDIO_CONST,d0
- divu d5,d0
- add.w d1,d0
- beq.s synth_rtper
- move.l #AUDIO_CONST,d5
- divu d0,d5
- synth_rtper cmp.w #113,d5 ;overflow??
- bhi.s synth_pern2h
- moveq #113,d5
- synth_pern2h rts
- ENDC
- sinetable dc.b 0,25,49,71,90,106,117,125,127,125,117,106,90,71,49
- dc.b 25,0,-25,-49,-71,-90,-106,-117,-125,-127,-125,-117
- dc.b -106,-90,-71,-49,-25,0
-
- EVEN
- XDEF _IntHandler
- _IntHandler: movem.l d2-d7/a2-a6,-(sp)
- lea DB,a6 ;don't expect a1 to contain DB address
- movea.l _module-DB(a6),a2
- move.l a2,d0
- beq.w plr_exit
- IFNE MIDI
- clr.b lastcmdbyte-DB(a6) ;no MIDI optimization
- ENDC
- tst.w mmd_pstate(a2)
- beq.w plr_exit
- IFNE MIDI
- clr.w bytesinnotebuff-DB(a6)
- ENDC
- movea.l mmd_songinfo(a2),a4
- moveq #0,d3
- move.b mmd_counter(a2),d3
- addq.b #1,d3
- cmp.b msng_tempo2(a4),d3
- bge.s plr_pnewnote ;play new note
- move.b d3,mmd_counter(a2)
- bne.w nonewnote ;do just fx
- ; --- new note!!
- plr_pnewnote: clr.b mmd_counter(a2)
- tst.w blkdelay-DB(a6)
- beq.s plr_noblkdelay
- subq.w #1,blkdelay-DB(a6)
- bne.w nonewnote
- ; --- now start to play it
- ; -------- GET ADDRESS OF NOTE DATA --------------------------------------
- plr_noblkdelay move.w mmd_pblock(a2),d0
- bsr.w GetNoteDataAddr
- moveq #0,d7 ;number of track
- moveq #0,d4
- lea trackdataptrs-DB(a6),a1
- ; -------- TRACK LOOP (FOR EACH TRACK) -----------------------------------
- plr_loop0: movea.l (a1)+,a5 ;get address of this track's struct
- ; ---------------- get the note numbers
- moveq #0,d3
- move.b (a3)+,d0 ;get the number of this note
- bpl.s plr_nothinote
- moveq #0,d0
- plr_nothinote move.b d0,trk_currnote(a5)
- beq.s plr_nosetprevn
- move.b d0,(a5)
- plr_nosetprevn move.b (a3),d3 ;instrument number
- addq.l #3,a3 ;adv. to next track
- clr.b trk_fxtype(a5)
- ; ---------------- check if there's an instrument number
- and.w #$3F,d3
- beq.s noinstnum
- ; ---------------- finally, save the number
- subq.b #1,d3
- move.b d3,trk_previnstr(a5) ;remember instr. number!
- ; ---------------- get the pointer of data's of this sample in Song-struct
- move.w d3,d0
- asl.w #3,d3
- lea 0(a4,d3.w),a0 ;a0 contains now address of it
- move.l a0,trk_previnstra(a5)
- ; ---------------- get volume
- move.b inst_svol(a0),trk_prevvol(a5) ;vol of this instr
- move.b inst_strans(a0),trk_stransp(a5)
- ; ---------------- remember some values of this instrument
- lea holdvals-DB(a6),a0
- adda.w d0,a0
- IFNE HOLD
- move.b (a0),trk_inithold(a5) ;hold
- move.b 63(a0),trk_initdecay(a5) ;decay
- ENDC
- move.b 2*63(a0),trk_finetune(a5) ;finetune
- move.b 6*63(a0),trk_outputdev(a5) ;output dev
- ; ---------------- remember transpose
- clr.w trk_soffset(a5) ;sample offset
- clr.b trk_miscflags(a5) ;misc.
- noinstnum addq.w #1,d7
- cmp.w numtracks-DB(a6),d7
- blt plr_loop0
- bsr.w DoPreFXLoop
- ; -------- NOTE PLAYING LOOP ---------------------------------------------
- moveq #0,d7
- lea trackdataptrs-DB(a6),a1
- plr_loop2 movea.l (a1)+,a5
- tst.b trk_fxtype(a5)
- bne.s plr_loop2_end
- move.b trk_currnote(a5),d1
- beq.s plr_loop2_end
- ; ---------------- play
- move.l a1,-(sp)
- ext.w d1
- moveq #0,d3
- move.b trk_previnstr(a5),d3 ;instr #
- movea.l trk_previnstra(a5),a3 ;instr data address
- move.b trk_inithold(a5),trk_noteoffcnt(a5) ;initialize hold
- bne.s plr_nohold0 ;not 0 -> OK
- st trk_noteoffcnt(a5) ;0 -> hold = 0xff (-1)
- ; ---------------- and finally:
- plr_nohold0 bsr _PlayNote ;play it
- move.l (sp)+,a1
- plr_loop2_end addq.w #1,d7
- cmp.w numtracks-DB(a6),d7
- blt.s plr_loop2
- ; -------- THE REST... ---------------------------------------------------
- bsr.s AdvSngPtr
- nonewnote bsr.w DoFX
- plr_endfx:
- IFNE MIDI
- bsr _StartDMA
- ENDC
- plr_exit: movem.l (sp)+,d2-d7/a2-a6
- rts
-
- ; and advance song pointers
- AdvSngPtr move.l mmd_pblock(a2),fxplineblk-DB(a6) ;store pline/block for fx
- move.w nextblockline-DB(a6),d1
- beq.s plr_advlinenum
- clr.w nextblockline-DB(a6)
- subq.w #1,d1
- bra.s plr_linenumset
- plr_advlinenum move.w mmd_pline(a2),d1 ;get current line #
- addq.w #1,d1 ;advance line number
- plr_linenumset cmp.w numlines-DB(a6),d1 ;advance block?
- bhi.s plr_chgblock ;yes.
- tst.b nextblock-DB(a6) ;command F00/1Dxx?
- beq.w plr_nochgblock ;no, don't change block
- ; -------- CHANGE BLOCK? -------------------------------------------------
- plr_chgblock tst.b nxtnoclrln-DB(a6)
- bne.s plr_noclrln
- moveq #0,d1 ;clear line number
- plr_noclrln tst.w mmd_pstate(a2) ;play block or play song
- bpl.w plr_nonewseq ;play block only...
- ; ********* BELOW CODE FOR MMD2 ONLY ************************************
- ; -------- CHANGE SEQUENCE -----------------------------------------------
- plr_skipseq move.w mmd_pseq(a2),d0 ;actually stored as << 2
- movea.l msng_pseqs(a4),a1 ;ptr to playseqs
- movea.l 0(a1,d0.w),a0 ;a0 = ptr to curr PlaySeq
- move.w mmd_pseqnum(a2),d0 ;get play sequence number
- tst.b nextblock-DB(a6)
- bmi.s plr_noadvseq ;Bxx sets nextblock to -1
- addq.w #1,d0 ;advance sequence number
- plr_noadvseq cmp.w 40(a0),d0 ;is this the highest seq number??
- blt.s plr_notagain ;no.
- ; -------- CHANGE SECTION ------------------------------------------------
- move.w mmd_psecnum(a2),d0 ;get section number
- addq.w #1,d0 ;increase..
- cmp.w msng_songlen(a4),d0 ;highest section?
- blt.s plr_nohisec
- moveq #0,d0 ;yes.
- plr_nohisec move.w d0,mmd_psecnum(a2) ;push back.
- add.w d0,d0
- movea.l msng_sections(a4),a0 ;section table
- move.w 0(a0,d0.w),d0 ;new playseqlist number
- add.w d0,d0
- add.w d0,d0
- move.w d0,mmd_pseq(a2)
- movea.l 0(a1,d0.w),a0 ;a0 = ptr to new PlaySeq
- moveq #0,d0 ;playseq OFFSET = 0
- ; -------- FETCH BLOCK NUMBER FROM SEQUENCE ------------------------------
- plr_notagain move.w d0,mmd_pseqnum(a2) ;remember new playseq pos
- add.w d0,d0
- move.w 42(a0,d0.w),d0 ;get number of the block
- bmi.s plr_skipseq ;neg. values for future expansion
- plr_changeblk
- IFNE CHECK
- cmp.w msng_numblocks(a4),d0 ;beyond last block??
- blt.s plr_nolstblk ;no..
- moveq #0,d0 ;play block 0
- ENDC
- plr_nolstblk move.w d0,mmd_pblock(a2) ;store block number
- plr_nonewseq clr.w nextblock-DB(a6) ;clear this if F00 set it
- ; ------------------------------------------------------------------------
- plr_nochgblock move.w d1,mmd_pline(a2) ;set new line number
-
- IFNE HOLD
- lea trackdataptrs-DB(a6),a5
- move.w mmd_pblock(a2),d0 ;pblock
- bsr.w GetBlockAddr
- move.w mmd_pline(a2),d0 ;play line
- move.b msng_tempo2(a4),d3 ;interrupts/note
- move.w (a0),d7 ;# of tracks
- add.w d0,d0
- add.w d0,d0 ;d0 = d0 * 4
- mulu d7,d0
- lea 8(a0,d0.l),a3
- subq.b #1,d7
- plr_chkhold movea.l (a5)+,a1 ;track data
- tst.b trk_noteoffcnt(a1) ;hold??
- bmi.s plr_holdend ;no.
- move.b (a3),d1 ;get the 1st byte..
- bne.s plr_hold1
- move.b 1(a3),d0
- and.b #$3F,d0
- beq.s plr_holdend ;don't hold
- bra.s plr_hold2
- plr_hold1 and.b #$7f,d1 ;note??
- beq.s plr_hold2 ;no, cont hold..
- move.b 2(a3),d1
- subq.b #3,d1 ;is there command 3 (slide)
- bne.s plr_holdend ;no -> end holding
- plr_hold2 add.b d3,trk_noteoffcnt(a1) ;continue holding...
- plr_holdend addq.l #4,a3 ;next note
- dbf d7,plr_chkhold
- ENDC
- rts
-
- ; *******************************************************************
- ; DoPreFXLoop: Loop and call DoPreFX
- ; *******************************************************************
- DoPreFXLoop:
- ; -------- PRE-FX COMMAND HANDLING LOOP ----------------------------------
- moveq #0,d5 ;command page count
- plr_loop1 move.w mmd_pblock(a2),d0
- bsr.w GetBlockAddr
- move.w d5,d1
- move.w mmd_pline(a2),d2
- bsr.w GetCmdPointer
- movea.l a0,a3
- moveq #0,d7 ;clear track count
- lea trackdataptrs-DB(a6),a1
- plr_loop1_1 movea.l (a1)+,a5
- move.b (a3),d0 ;command #
- beq.s plr_loop1_end
- moveq #0,d4
- move.b 1(a3),d4 ;data byte
- and.w #$3F,d0
- bsr.s DoPreFX
- or.b d0,trk_fxtype(a5)
- plr_loop1_end adda.w d6,a3 ;next track...
- addq.w #1,d7
- cmp.w numtracks-DB(a6),d7
- blt.s plr_loop1_1
- addq.w #1,d5
- cmp.w numpages-DB(a6),d5
- bls.s plr_loop1
- rts
-
- ; *******************************************************************
- ; DoPreFX: Perform effects that must be handled before note playing
- ; *******************************************************************
- ; args: a6 = DB d0 = command number (w)
- ; a5 = track data d5 = note number
- ; a4 = song d4 = data
- ; d7 = track #
- ; returns: d0 = 0: play - d0 = 1: don't play
-
- rtplay MACRO
- moveq #0,d0
- rts
- ENDM
- rtnoplay MACRO
- moveq #1,d0
- rts
- ENDM
-
- DoPreFX: add.b d0,d0 ;* 2
- move.w f_table(pc,d0.w),d0
- jmp fst(pc,d0.w)
- fst
- f_table dc.w fx-fst,fx-fst,fx-fst,f_03-fst,fx-fst,fx-fst,fx-fst,fx-fst
- dc.w f_08-fst,f_09-fst,fx-fst,f_0b-fst,f_0c-fst,fx-fst,f_0e-fst,f_0f-fst
- dc.w fx-fst,fx-fst,fx-fst,fx-fst,fx-fst,f_15-fst,f_16-fst,fx-fst
- dc.w fx-fst,f_19-fst,fx-fst,fx-fst,f_1c-fst,f_1d-fst,f_1e-fst,f_1f-fst
- dc.w f_20-fst,fx-fst,fx-fst,fx-fst,fx-fst,fx-fst,fx-fst,fx-fst
- dc.w fx-fst,fx-fst,fx-fst,fx-fst,fx-fst,fx-fst,f_2e-fst,f_2f-fst
- dc.w fx-fst,fx-fst,fx-fst,fx-fst,fx-fst,fx-fst,fx-fst,fx-fst
- dc.w fx-fst,fx-fst,fx-fst,fx-fst,fx-fst,fx-fst,fx-fst,fx-fst
- ; ---------------- tempo (F)
- f_0f tst.b d4 ;test effect qual..
- beq fx0fchgblck ;if effect qualifier (last 2 #'s)..
- cmp.b #$f0,d4 ;..is zero, go to next block
- bhi.s fx0fspecial ;if it's F1-FF something special
- ; ---------------- just an ordinary "change tempo"-request
- moveq #0,d0 ;will happen!!!
- move.b d4,d0
- bsr _SetTempo ;change The Tempo
- fx rtplay
- ; ---------------- no, it was FFx, something special will happen!!
- fx0fspecial: cmp.b #$f2,d4
- beq.s f_1f
- cmp.b #$f4,d4
- beq.s f_1f
- cmp.b #$f5,d4
- bne.s isfxfe
- ; ---------------- FF2 (or 1Fxx)
- f_1f
- IFNE HOLD
- move.b trk_inithold(a5),trk_noteoffcnt(a5) ;initialize hold
- bne.s f_1frts ;not 0 -> OK
- st trk_noteoffcnt(a5) ;0 -> hold = 0xff (-1)
- ENDC
- f_1frts rtnoplay
- isfxfe: cmp.b #$fe,d4
- bne.s notcmdfe
- ; ---------------- it was FFE, stop playing
- clr.w mmd_pstate(a2)
- bsr.w SoundOff
- adda.w #8,sp ;2 subroutine levels
- bra.w plr_exit
- f_ffe_no8 rtplay
- notcmdfe: cmp.b #$fd,d4 ;change period
- bne.s isfxff
- ; ---------------- FFD, change the period, don't replay the note
- IFNE CHECK
- cmp.w maxaudiotrk-DB(a6),d7 ;no tracks above 4, thank you!!
- bge.s f_0f_rts
- ENDC
- move.l trk_periodtbl(a5),d1 ;period table
- beq.s f_1frts
- movea.l d1,a0
- move.b trk_currnote(a5),d0
- subq.b #1,d0 ;sub 1 to make "real" note number
- IFNE CHECK
- bmi.s f_1frts
- ENDC
- add.b msng_playtransp(a4),d0
- add.b trk_stransp(a5),d0
- add.w d0,d0
- bmi.s f_1frts
- move.w 0(a0,d0.w),trk_prevper(a5) ;get & push the period
- rtnoplay
- isfxff cmp.b #$ff,d4 ;note off??
- bne.s isfxf7
- move.w d7,d0
- move.l a1,-(sp)
- bsr.w _ChannelOff
- move.l (sp)+,a1
- rtplay
- isfxf7
- IFNE MIDI
- cmp.b #$f7,d4 ;wait SysX
- bne.s f_0f_rts
- tst.b sysx-DB(a6)
- beq.s f_0f_rts
- move.w #2,blkdelay-DB(a6)
- ENDC
- f_0f_rts rtplay
- ; ---------------- F00, called Pattern Break in ST
- fx0fchgblck: move.b #1,nextblock-DB(a6) ;next block????...YES!!!! (F00)
- bra.s f_0f_rts
- ; ---------------- was not Fxx, then it's something else!!
- f_0e
- IFNE CHECK
- cmp.b maxaudiotrk-DB(a6),d7
- bge.s f_0e_rts
- ENDC
- bset #0,trk_miscflags(a5)
- move.b d4,trk_wfcmd+1(a5) ;set waveform command position ptr
- f_0e_rts rtplay
- ; ---------------- change volume
- f_0c move.b d4,d0
- bpl.s plr_nosetdefvol
- and.b #$7F,d0
- IFNE CHECK
- cmp.b #64,d0
- bgt.s go_nocmd
- ENDC
- moveq #0,d1
- move.b trk_previnstr(a5),d1
- asl.w #3,d1
- move.b d0,inst_svol(a4,d1.w) ;set new svol
- bra.s plr_setvol
- plr_nosetdefvol btst #4,msng_flags(a4) ;look at flags
- bne.s volhex
- lsr.b #4,d0 ;get number from left
- mulu #10,d0 ;number of tens
- move.b d4,d1 ;get again
- and.b #$0f,d1 ;this time don't get tens
- add.b d1,d0 ;add them
- volhex:
- IFNE CHECK
- cmp.b #64,d0
- bhi.s go_nocmd
- ENDC
- plr_setvol move.b d0,trk_prevvol(a5)
- go_nocmd rtplay
- ; ---------------- tempo2 change??
- f_09
- IFNE CHECK
- and.b #$1F,d4
- bne.s fx9chk
- moveq #$20,d4
- ENDC
- fx9chk: move.b d4,msng_tempo2(a4)
- f_09_rts rtplay
- ; ---------------- block delay
- f_1e tst.w blkdelay-DB(a6)
- bne.s f_1e_rts
- addq.w #1,d4
- move.w d4,blkdelay-DB(a6)
- f_1e_rts rtplay
- ; ---------------- finetune
- f_15
- IFNE CHECK
- cmp.b #7,d4
- bgt.s f_15_rts
- cmp.b #-8,d4
- blt.s f_15_rts
- ENDC
- move.b d4,trk_finetune(a5)
- f_15_rts rtplay
- ; ---------------- repeat loop
- f_16 tst.b d4
- bne.s plr_dorpt
- move.w mmd_pline(a2),rptline-DB(a6)
- bra.s f_16_rts
- plr_dorpt tst.w rptcounter-DB(a6)
- beq.s plr_newrpt
- subq.w #1,rptcounter-DB(a6)
- beq.s f_16_rts
- bra.s plr_setrptline
- plr_newrpt move.b d4,rptcounter+1-DB(a6)
- plr_setrptline move.w rptline-DB(a6),d0
- addq.w #1,d0
- move.w d0,nextblockline-DB(a6)
- f_16_rts rtplay
- ; ---------------- preset change
- f_1c
- IFNE MIDI
- cmp.b #$80,d4
- bhi.s f_1c_rts
- moveq #0,d1
- move.b trk_previnstr(a5),d1
- add.w d1,d1
- lea ext_midipsets-DB(a6),a0
- ext.w d4
- move.w d4,0(a0,d1.w) ;set MIDI preset
- ENDC
- f_1c_rts rtplay
- ; ---------------- note off time set??
- f_08
- IFNE HOLD
- IFNE MIDI
- move.l trk_previnstra(a5),d0
- beq.s 1$
- move.l d0,a0
- tst.b inst_midich(a0)
- bne.s 2$ ;two-digit hold for MIDI instrs
- ENDC
- 1$ move.b d4,d0
- lsr.b #4,d0 ;extract left nibble
- and.b #$0f,d4 ; " " right " "
- move.b d0,trk_initdecay(a5) ;left = decay
- 2$ move.b d4,trk_inithold(a5) ;right = hold
- ENDC
- rtplay
- ; ---------------- sample begin offset
- f_19 lsl.w #8,d4
- move.w d4,trk_soffset(a5)
- f_19_rts rtplay
- ; ---------------- cmd Bxx, "position jump"
- f_0b
- IFNE CHECK
- chk0b_mmd2 move.w mmd_pseq(a2),d0 ;get seq number
- movea.l msng_pseqs(a4),a0 ;ptr to playseqs
- movea.l 0(a0,d0.w),a0 ;a0 = ptr to curr PlaySeq
- cmp.w 40(a0),d4 ;test song length
- bhi.s f_0b_rts
- chk0b_end
- ENDC
- move.w d4,mmd_pseqnum(a2)
- st nextblock-DB(a6) ; = 1
- f_0b_rts rtplay
- ; ---------------- cmd 1Dxx, jump to next seq, line # specified
- f_1d move.w #$1ff,nextblock-DB(a6)
- addq.w #1,d4
- move.w d4,nextblockline-DB(a6)
- rtplay
- ; ---------------- try portamento (3)
- f_03
- IFNE CHECK
- cmp.w maxaudiotrk-DB(a6),d7
- bge.s f_03_rts
- ENDC
- moveq #0,d0
- move.b trk_currnote(a5),d0
- subq.b #1,d0 ;subtract note number
- bmi.s plr_setfx3spd ;0 -> set new speed
- move.l trk_periodtbl(a5),d1
- beq.s f_03_rts
- movea.l d1,a0
- add.b msng_playtransp(a4),d0 ;play transpose
- add.b trk_stransp(a5),d0 ;and instrument transpose
- bmi.s f_03_rts ;again.. too low
- add.w d0,d0
- move.w 0(a0,d0.w),trk_porttrgper(a5) ;period of this note is the target
- plr_setfx3spd: tst.b d4 ;qual??
- beq.s f_03_rts ;0 -> do nothing
- move.b d4,trk_prevportspd(a5) ;store speed
- f_03_rts rtnoplay
-
- ; ---------------- command 20 (backwards)
- f_20 tst.b d4
- bne.s 1$
- bset #6,trk_miscflags(a5) ;play backwards
- 1$ rtplay
- ; ---------------- command 2E (panpot)
- XREF Mix_FX2E
- f_2e jsr Mix_FX2E(pc)
- rtplay
- ; ---------------- command 2F (fx settings)
- XREF Mix_FX2F
- f_2f jsr Mix_FX2F(pc)
- rtplay
-
- ; *******************************************************************
- ; DoFX: Handle effects, hold/fade etc.
- ; *******************************************************************
- DoFX moveq #0,d3
- move.b mmd_counter(a2),d3
- IFNE HOLD
- lea trackdataptrs-DB(a6),a1
- ; Loop 1: Hold/Fade handling
- moveq #0,d7 ;clear track count
- dofx_loop1 movea.l (a1)+,a5
- bsr.w HoldAndFade
- addq.w #1,d7
- cmp.w numtracks-DB(a6),d7
- blt.s dofx_loop1
- ENDC
- ; Loop 2: Track command handling
- moveq #0,d5 ;command page count
- dofx_loop2 move.w fxplineblk-DB(a6),d0
- bsr.w GetBlockAddr
- movea.l a0,a3
- bsr.w StoreBlockDims
- dofx_sbd_mmd0 move.w d5,d1
- move.w fxplineblk+2-DB(a6),d2
- movea.l a3,a0
- bsr.s GetCmdPointer
- movea.l a0,a3
- moveq #0,d7 ;clear track count
- lea trackdataptrs-DB(a6),a1
- dofx_loop2_1 movea.l (a1)+,a5
- moveq #0,d4
- move.b (a3),d0 ;command #
- move.b 1(a3),d4 ;data byte
- and.w #$1F,d0
- dofx_mmd0maskd tst.b trk_fxtype(a5)
- bgt.s dofx_lend2_1 ;1 = skip
- IFNE MIDI
- beq.s dofx_chfx
- bsr.w MIDIFX
- bra.s dofx_lend2_1
- ENDC
- IFEQ MIDI
- bne.s dofx_lend2_1
- ENDC
- dofx_chfx bsr.w ChannelFX
- dofx_lend2_1 adda.w d6,a3 ;next track...
- addq.w #1,d7
- cmp.w numtracks-DB(a6),d7
- blt.s dofx_loop2_1
- addq.w #1,d5
- cmp.w numpages-DB(a6),d5
- bls.s dofx_loop2
- ; Loop 3: Updating audio hardware
- moveq #0,d7 ;clear track count
- lea trackdataptrs-DB(a6),a1
- dofx_loop3 movea.l (a1)+,a5
- IFNE HOLD
- tst.b trk_fxtype(a5)
- bne.s dofx_lend3 ;only in case 0 (norm)
- ENDC
- IFEQ HOLD
- cmp.w maxaudiotrk-DB(a6),d7
- bge.s dofx_stopl3
- ENDC
- bsr.w UpdatePerVol
- dofx_lend3 addq.w #1,d7
- cmp.w numtracks-DB(a6),d7
- blt.s dofx_loop3
- dofx_stopl3 rts
-
- ; *******************************************************************
- ; GetCmdPointer: Return command pointer for track 0
- ; *******************************************************************
- ; args: a0 = block pointer
- ; d1 = page number
- ; d2 = line number
- ; a2 = module
- ; result: a0 = command pointer (i.e. trk 0 note + 2)
- ; d6 = track advance (bytes)
- ; scratches: d0, d1, d2, a0
- ; Note: no num_pages check! If numpages > 0 it can be assumed that
- ; extra pages exist.
-
- GetCmdPointer
- mulu (a0),d2 ;d2 = line # * numtracks
- add.l d2,d2 ;d2 *= 2...
- subq.w #1,d1
- bmi.s gcp_page0
- movea.l 4(a0),a0
- movea.l 12(a0),a0
- add.w d1,d1
- add.w d1,d1
- movea.l 4(a0,d1.w),a0 ;command data
- adda.l d2,a0
- moveq #2,d6
- rts
- gcp_page0 add.l d2,d2 ;d2 *= 4
- lea 10(a0,d2.l),a0 ;offs: 4 = header, 2 = note
- moveq #4,d6 ;track advance (bytes)
- rts
-
- ; *******************************************************************
- ; GetBlockAddr: Return pointer to block
- ; *******************************************************************
- ; args: d0 = block number
- ; result: a0 = block pointer
- ; scratches: d0, a0
-
- GetBlockAddr movea.l mmd_blockarr(a2),a0
- add.w d0,d0
- add.w d0,d0
- movea.l 0(a0,d0.w),a0
- rts
-
- ; *******************************************************************
- ; GetNoteDataAddr: Check & return addr. of current note
- ; *******************************************************************
- ;args: d0 = pblock a6 = DB
- ;returns: a3 = address
- ;scratches: d0, a0, d1
-
- GetNoteDataAddr bsr.w GetBlockAddr
- movea.l a0,a3
- bsr.w StoreBlockDims
- move.w numlines-DB(a6),d1
- move.w mmd_pline(a2),d0
- cmp.w d1,d0 ;check if block end exceeded...
- bls.s plr_nolinex
- move.w d1,d0
- plr_nolinex add.w d0,d0
- add.w d0,d0 ;d0 = d0 * 4
- mulu numtracks-DB(a6),d0
- lea 8(a3,d0.l),a3 ;address of current note
- rts
-
- ; *******************************************************************
- ; StoreBlockDims: Store block dimensions
- ; *******************************************************************
- ; args: a0 = block ptr, a6 = DB
-
- StoreBlockDims move.l (a0)+,numtracks-DB(a6) ;numtracks & lines
- tst.l (a0) :BlockInfo
- beq.s sbd_1page
- movea.l (a0),a0
- move.l 12(a0),d0 ;BlockInfo.pagetable
- beq.s sbd_1page
- movea.l d0,a0
- move.w (a0),numpages-DB(a6) ;num_pages
- rts
- sbd_1page clr.w numpages-DB(a6)
- rts
-
- ; *******************************************************************
- ; HoldAndFade: Handle hold/fade
- ; *******************************************************************
- ; args: a5 = track data
- ; a6 = DB
- ; d7 = track #
- ; scratches: d0, d1, a0
-
- IFNE HOLD
- HoldAndFade
- IFNE MIDI
- tst.b trk_prevmidin(a5) ;is it MIDI??
- bne.w plr_haf_midi
- ENDC
- IFNE CHECK
- cmp.w maxaudiotrk-DB(a6),d7
- bge.w plr_haf_midi ;no non-MIDI effects in tracks 4 - 15
- ENDC
- tst.b trk_noteoffcnt(a5)
- bmi.s plr_haf_noholdexp
- subq.b #1,trk_noteoffcnt(a5)
- bpl.s plr_haf_noholdexp
- IFNE SYNTH
- tst.b trk_synthtype(a5) ;synth/hybrid??
- beq.s plr_nosyndec
- move.b trk_decay(a5),trk_volcmd+1(a5) ;set volume command pointer
- clr.b trk_volwait(a5) ;abort WAI
- bra.s plr_haf_noholdexp
- ENDC
- plr_nosyndec move.b trk_decay(a5),trk_fadespd(a5) ;set fade...
- bne.s plr_haf_noholdexp ;if > 0, don't stop sound
- move.w d7,d0
- move.l a1,-(sp)
- bsr.w _ChannelOff
- movea.l (sp)+,a1
- plr_haf_noholdexp
- move.b trk_fadespd(a5),d0 ;fade??
- beq.s plr_haf_dofx ;no.
- sub.b d0,trk_prevvol(a5)
- bpl.s plr_nofade2low
- clr.b trk_prevvol(a5)
- clr.b trk_fadespd(a5) ;fade no more
- plr_nofade2low
- plr_haf_dofx clr.b trk_fxtype(a5)
- plr_haf_rts rts
- ; MIDI version
- plr_haf_midi
- st trk_fxtype(a5)
- IFNE MIDI
- tst.b trk_noteoffcnt(a5)
- bmi.s plr_haf_rts
- subq.b #1,trk_noteoffcnt(a5)
- bpl.s plr_haf_rts
- move.b trk_prevmidin(a5),d1
- beq.s plr_haf_rts
- lea noteondata-DB(a6),a0
- exg.l a5,a1
- bsr.w choff_midi
- exg.l a5,a1
- ENDC
- rts
- ;hold
- ENDC
-
- ; *******************************************************************
- ; ChannelFX: Do an effect on a channel
- ; *******************************************************************
- ;args: d3 = counter
- ; a4 = song struct d4 = command qual (long, byte used)
- ; a5 = track data ptr
- ; a6 = DB d0 = command (long, byte used)
- ; d7 = track (channel) number
- ;scratches: d0, d1, d4, a0
-
- ChannelFX add.b d0,d0 ;* 2
- move.w fx_table(pc,d0.w),d0
- jmp fxs(pc,d0.w)
- fxs:
- fx_table dc.w fx_00-fxs,fx_01-fxs,fx_02-fxs,fx_03-fxs,fx_04-fxs
- dc.w fx_05-fxs,fx_06-fxs,fx_07-fxs,fx_xx-fxs,fx_xx-fxs
- dc.w fx_0a-fxs,fx_xx-fxs,fx_0c-fxs,fx_0d-fxs,fx_xx-fxs
- dc.w fx_0f-fxs
- dc.w fx_10-fxs,fx_11-fxs,fx_12-fxs,fx_13-fxs,fx_14-fxs
- dc.w fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_18-fxs,fx_xx-fxs
- dc.w fx_1a-fxs,fx_1b-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs
- dc.w fx_1f-fxs
- dc.w fx_20-fxs,fx_21-fxs,fx_22-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs
- dc.w fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs
- dc.w fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs
- dc.w fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs
- ; **************************************** Effect 01 & 02 *
- fx_02 neg.w d4
- fx_01 tst.b d3
- bne.s fx_01nocnt0
- btst #5,msng_flags(a4) ;FLAG_STSLIDE??
- bne.s fx_xx
- fx_01nocnt0 move.l #AUDIO_CONST,d1
- move.l d1,d0
- tst.w trk_prevper(a5)
- beq.s 1$
- divu trk_prevper(a5),d0
- sub.w d4,d0
- beq.s 1$
- divu d0,d1
- move.w d1,trk_prevper(a5)
- 1$ ;fx_xx is just a RTS
- fx_xx rts
- ; **************************************** Effect 11 ******
- fx_11 tst.b d3
- beq.s fx_01nocnt0
- fx_11rts rts
- ; **************************************** Effect 12 ******
- fx_12 neg.w d4
- tst.b d3
- beq.s fx_01nocnt0
- fx_12rts rts
- ; **************************************** Effect 21 ******
- fx_21 move.w trk_prevper(a5),d0
- move.w d0,d1
- mulu d4,d0
- lsl.l #5,d0
- swap d0
- add.w d0,d1
- bcc.s 1$
- moveq #-1,d1 ;max. freq = 65535 Hz
- 1$ move.w d1,trk_prevper(a5)
- rts
- ; **************************************** Effect 22 ******
- fx_22 move.w trk_prevper(a5),d0
- move.w d0,d1
- mulu d4,d0
- lsl.l #5,d0
- swap d0
- sub.w d0,d1
- bcc.s 1$
- moveq #1,d1
- 1$ move.w d1,trk_prevper(a5)
- rts
- ; **************************************** Effect 00 ******
- fx_00 tst.b d4 ;both fxqualifiers are 0s: no arpeggio
- beq.s fx_00rts
- move.l d3,d0
- divu #3,d0
- swap d0
- subq.b #1,d0
- bgt.s fx_arp2
- blt.s fx_arp0
- and.b #$0f,d4
- bra.s fx_doarp
- fx_arp0 lsr.b #4,d4
- bra.s fx_doarp
- fx_arp2 moveq #0,d4
- fx_doarp: move.b (a5),d0
- subq.b #1,d0 ;-1 to make it 0 - 127
- add.b msng_playtransp(a4),d0 ;add play transpose
- add.b trk_stransp(a5),d0 ;add instrument transpose
- add.b d0,d4
- move.l trk_periodtbl(a5),d1
- beq.s fx_00rts
- movea.l d1,a0
- add.b d0,d0
- move.w 0(a0,d0.w),d0 ;base note period
- add.b d4,d4
- sub.w 0(a0,d4.w),d0 ;calc difference from base note
- move.w d0,trk_arpadjust(a5)
- fx_00rts rts
- ; **************************************** Effect 04 ******
- fx_14 move.b #6,trk_vibshift(a5)
- bra.s vib_cont
- fx_04 move.b #5,trk_vibshift(a5)
- vib_cont tst.b d3
- bne.s nonvib
- move.b d4,d1
- beq.s nonvib
- and.w #$0f,d1
- beq.s plr_chgvibspd
- move.w d1,trk_vibrsz(a5)
- plr_chgvibspd and.b #$f0,d4
- beq.s nonvib
- lsr.b #3,d4
- and.b #$3e,d4
- move.b d4,trk_vibrspd(a5)
- nonvib move.b trk_vibroffs(a5),d0
- lsr.b #2,d0
- and.w #$1f,d0
- moveq #0,d1
- lea sinetable(pc),a0
- move.b 0(a0,d0.w),d0
- ext.w d0
- muls trk_vibrsz(a5),d0
- move.b trk_vibshift(a5),d1
- asr.w d1,d0
- move.b trk_vibrspd(a5),d1
- add.b d1,trk_vibroffs(a5)
- move.l #AUDIO_CONST,d1
- move.l d1,d4
- tst.w trk_prevper(a5)
- beq.s 1$
- divu trk_prevper(a5),d4
- add.w d0,d4
- beq.s 1$
- divu d4,d1
- sub.w trk_prevper(a5),d1
- move.w d1,trk_vibradjust(a5)
- 1$
- fx_04rts rts
- ; **************************************** Effect 06 ******
- fx_06: tst.b d3
- bne.s fx_06nocnt0
- btst #5,msng_flags(a4)
- bne.s fx_04rts
- fx_06nocnt0 bsr.s plr_volslide ;Volume slide
- bra.s nonvib ;+ Vibrato
- ; **************************************** Effect 07 ******
- fx_07 tst.b d3
- bne.s nontre
- move.b d4,d1
- beq.s nontre
- and.w #$0f,d1
- beq.s plr_chgtrespd
- move.w d1,trk_tremsz(a5)
- plr_chgtrespd and.b #$f0,d4
- beq.s nontre
- lsr.b #2,d4
- and.b #$3e,d4
- move.b d4,trk_tremspd(a5)
- nontre move.b trk_tremoffs(a5),d0
- lsr.b #3,d0
- and.w #$1f,d0
- lea sinetable(pc),a0
- move.b 0(a0,d0.w),d1
- ext.w d1
- muls trk_tremsz(a5),d1
- asr.w #7,d1
- move.b trk_tremspd(a5),d0
- add.b d0,trk_tremoffs(a5)
- add.b trk_prevvol(a5),d1
- bpl.s tre_pos
- moveq #0,d1
- tre_pos cmp.b #64,d1
- ble.s tre_no2hi
- moveq #64,d1
- tre_no2hi move.b d1,trk_tempvol(a5)
- rts
- ; ********* VOLUME SLIDE FUNCTION *************************
- plr_volslide move.b d4,d0
- moveq #0,d1
- move.b trk_prevvol(a5),d1 ;move previous vol to d1
- and.b #$f0,d0
- bne.s crescendo
- sub.b d4,d1 ;sub from prev. vol
- voltest0 bpl.s novolover64
- moveq #0,d1 ;volumes under zero not accepted
- bra.s novolover64
- crescendo: lsr.b #4,d0
- add.b d0,d1
- voltest cmp.b #64,d1
- ble.s novolover64
- moveq #64,d1
- novolover64 move.b d1,trk_prevvol(a5)
- volsl_rts rts
- ; **************************************** Effect 0D/0A ***
- fx_0a:
- fx_0d: tst.b d3
- bne.s plr_volslide
- btst #5,msng_flags(a4)
- beq.s plr_volslide
- rts
- ; **************************************** Effect 05 ******
- fx_05: tst.b d3
- bne.s fx_05nocnt0
- btst #5,msng_flags(a4)
- bne.s fx_05rts
- fx_05nocnt0 bsr.s plr_volslide
- bra.s fx_03nocnt0
- fx_05rts rts
- ; **************************************** Effect 1A ******
- fx_1a tst.b d3
- bne.s volsl_rts
- move.b trk_prevvol(a5),d1
- add.b d4,d1
- bra.s voltest
- ; **************************************** Effect 1B ******
- fx_1b tst.b d3
- bne.s volsl_rts
- move.b trk_prevvol(a5),d1
- sub.b d4,d1
- bra.s voltest0
- ; **************************************** Effect 03 ******
- fx_03: tst.b d3
- bne.s fx_03nocnt0
- btst #5,msng_flags(a4)
- bne.s fx_03rts
- fx_03nocnt0 move.w trk_porttrgper(a5),d0 ;d0 = target period
- beq.s fx_03rts
- move.w trk_prevper(a5),d1 ;d1 = curr. period
- move.b trk_prevportspd(a5),d4 ;get prev. speed
- cmp.w d0,d1
- bhi.s subper ;curr. period > target period
- move.l #AUDIO_CONST,d1
- move.l d1,d0
- tst.w trk_prevper(a5)
- beq.s fx_03rts
- divu trk_prevper(a5),d0
- sub.w d4,d0
- bls.s targreached ;carry or zero set
- divu d0,d1
- cmp.w trk_porttrgper(a5),d1
- bcs.s targnreach
- bra.s targreached
- subper: move.l #AUDIO_CONST,d1
- move.l d1,d0
- tst.w trk_prevper(a5)
- beq.s fx_03rts
- divu trk_prevper(a5),d0
- add.w d4,d0
- beq.s targreached
- divu d0,d1
- cmp.w trk_porttrgper(a5),d1
- bhi.s targnreach
- targreached: move.w trk_porttrgper(a5),d1 ;eventually push target period
- clr.w trk_porttrgper(a5) ;now we can forget everything
- targnreach: move.w d1,trk_prevper(a5)
- fx_03rts rts
- ; **************************************** Effect 13 ******
- fx_13: cmp.b #3,d3
- bge.s fx_13rts ;if counter < 3
- neg.w d4
- move.w d4,trk_vibradjust(a5) ;subtract effect qual...
- fx_13rts rts
- ; *********************************************************
- fx_0c: tst.b d3
- bne.s fx_13rts
- dvc_0 move.b trk_prevvol(a5),d1
- rts
- ; **************************************** Effect 10 ******
- fx_10:
- IFNE MIDI
- tst.b d3
- bne.s fx_13rts
- move.w d4,d0
- bra.w _InitMIDIDump
- ENDC
- IFEQ MIDI
- rts
- ENDC
- ; **************************************** Effect 18 ******
- fx_18 cmp.b d4,d3
- bne.s fx_18rts
- clr.b trk_prevvol(a5)
- fx_18rts rts
- ; **************************************** Effect 1F ******
- fx_1f move.b d4,d1
- lsr.b #4,d4 ;note delay
- beq.s nonotedelay
- cmp.b d4,d3 ;compare to counter
- blt.s fx_18rts ;tick not reached
- bne.s nonotedelay
- bra playfxnote ;trigger note
- nonotedelay and.w #$0f,d1 ;retrig?
- beq.s fx_18rts
- moveq #0,d0
- move.b d3,d0
- divu d1,d0
- swap d0 ;get modulo of counter/tick
- tst.w d0
- bne.s fx_18rts
- bra playfxnote ;retrigger
- ; **************************************** Effect 20 ******
- XREF Mix_FX20
- fx_20 tst.b d3
- bne.s fx_20rts
- move.b d4,d0
- ext.w d0
- jmp Mix_FX20(pc)
- fx_20rts rts
- ; **************************************** Effect 0F ******
- ; see below...
- ; *********************************************************
-
- ; *******************************************************************
- ; UpdatePerVol: Update audio registers (period & volume) after FX
- ; *******************************************************************
- ; args: a6 = DB d7 = channel #
- ; a5 = track data
- ; scratches: d0, d1, a0, d5
- UpdatePerVol cmp.w maxaudiotrk-DB(a6),d7
- bge.s plr_upv_rts
- move.w trk_prevper(a5),d5
- IFNE SYNTH
- move.l trk_synthptr(a5),d0
- beq.s plr_upv_nosynth
- move.l a1,-(sp)
- bsr.w synth_start
- move.l (sp)+,a1
- ENDC
- plr_upv_nosynth add.w trk_vibradjust(a5),d5
- sub.w trk_arpadjust(a5),d5
- clr.l trk_vibradjust(a5) ;clr both adjusts
- moveq #0,d0
- move.b trk_tempvol(a5),d0
- bpl.s plr_upv_setvol
- move.b trk_prevvol(a5),d0
- plr_upv_setvol st trk_tempvol(a5)
- ; -------- GetRelVol: Calculate track volume -----------------------------
- ; track # = d7, note vol = d0, song = a4
- IFNE RELVOL
- mulu trk_trackvol(a5),d0 ;d0 = master v. * track v. * volume
- lsr.w #8,d0
- ENDC
- XREF _MixSetTrkPeriod,_MixSetTrkVol
- move.l a1,-(sp)
- jsr _MixSetTrkVol(pc)
- movea.l (sp)+,a1
- move.w d5,d1
- jmp _MixSetTrkPeriod(pc)
- plr_upv_rts rts
-
- ; **** a separate routine for handling command 0F
- fx_0f cmp.b #$f1,d4
- bne.s no0ff1
- cmp.b #3,d3
- beq.s playfxnote
- rts
- no0ff1: cmp.b #$f2,d4
- bne.s no0ff2
- cmp.b #3,d3
- beq.s playfxnote
- rts
- no0ff2: cmp.b #$f3,d4
- bne.s no0ff3
- move.b d3,d0
- beq.s cF_rts
- and.b #1,d0 ;is 2 or 4
- bne.s cF_rts
- playfxnote: moveq #0,d1
- move.b trk_currnote(a5),d1 ;get note # of curr. note
- beq.s cF_rts
- move.b trk_noteoffcnt(a5),d0 ;get hold counter
- bmi.s pfxn_nohold ;no hold, or hold over
- add.b d3,d0 ;increase by counter val
- bra.s pfxn_hold
- pfxn_nohold move.b trk_inithold(a5),d0 ;get initial hold
- bne.s pfxn_hold
- st d0
- pfxn_hold move.b d0,trk_noteoffcnt(a5)
- movem.l a1/a3/d2-d3/d5-d6,-(sp)
- moveq #0,d3
- move.b trk_previnstr(a5),d3 ;and prev. sample #
- movea.l trk_previnstra(a5),a3
- bsr _PlayNote
- movem.l (sp)+,a1/a3/d2-d3/d5-d6
- cF_rts rts
- no0ff3: cmp.b #$f4,d4 ;triplet cmd 1
- bne.s no0ff4
- moveq #0,d0
- move.b msng_tempo2(a4),d0
- divu #3,d0
- cmp.b d0,d3
- beq.s playfxnote
- rts
- no0ff4 cmp.b #$f5,d4 ;triplet cmd 2
- bne.s no0ff5
- moveq #0,d0
- move.b msng_tempo2(a4),d0
- divu #3,d0
- add.w d0,d0
- cmp.b d0,d3
- beq.s playfxnote
- rts
- no0ff5 cmp.b #$f7,d4
- bne.s no0ff7
- IFNE MIDI
- tst.b d3
- bne.s 1$
- tst.b sysx-DB(a6)
- beq.s 1$
- addq.w #1,blkdelay-DB(a6)
- ENDC
- 1$ rts
- no0ff7 cmp.b #$f8,d4 ;f8 = filter off
- beq.s plr_filteroff
- cmp.b #$f9,d4 ;f9 = filter on
- bne.s cF_rts
- bclr #1,$bfe001
- bset #0,msng_flags(a4)
- rts
- plr_filteroff: bset #1,$bfe001
- bclr #0,msng_flags(a4)
- rts
-
- ; -------- AUDIO DMA ROUTINE ---------------------------------------------
- _StartDMA: ;Only used for triggering MIDI notes
- IFNE MIDI
- lea bytesinnotebuff-DB(a6),a0
- move.w (a0)+,d0
- bne.w _AddMIDId
- rts
- ENDC
-
- _SetTempo:
- XREF _SetMixTempo
- movea.l a4,a0
- jmp _SetMixTempo(pc)
-
- IFNE MIDI
- MIDIFX add.b d0,d0 ;* 2
- move.w midicmd_table(pc,d0.w),d0
- jmp midifx(pc,d0.w)
- midifx
- midicmd_table dc.w mfx_00-midifx,mfx_01-midifx,mfx_02-midifx,mfx_03-midifx,mfx_04-midifx
- dc.w mfx_05-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx
- dc.w mfx_0a-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_0d-midifx,mfx_0e-midifx
- dc.w mfx_0f-midifx
- dc.w mfx_10-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_13-midifx
- dc.w mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_17-midifx
- dc.w mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx
- dc.w mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,fx_1f-midifx
- dc.w mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx
- dc.w mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx
- dc.w mfx_rts-midifx,mfx_31-midifx,mfx_32-midifx,mfx_33-midifx,mfx_34-midifx,mfx_35-midifx,mfx_36-midifx,mfx_37-midifx
- dc.w mfx_38-midifx,mfx_39-midifx,mfx_3A-midifx,mfx_3B-midifx,mfx_3C-midifx,mfx_3D-midifx,mfx_3E-midifx,mfx_3F-midifx
-
- mfx_01 lea prevmidipbend-DB(a6),a0
- moveq #0,d1
- move.b trk_prevmidich(a5),d1 ;get previous midi channel
- add.b d1,d1 ;UWORD index
- tst.b d4 ;x100??
- beq.s resetpbend
- move.w 0(a0,d1.w),d0 ;get previous pitch bend
- lsl.w #3,d4 ;multiply bend value by 8
- add.w d4,d0
- cmp.w #$3fff,d0
- bls.s bendpitch
- move.w #$3fff,d0
- bendpitch: move.w d0,0(a0,d1.w) ;save current pitch bend
- lsr.b #1,d1 ;back to UBYTE
- or.b #$e0,d1
- lea noteondata-DB(a6),a0
- move.b d1,(a0) ;midi command & channel
- move.b d0,1(a0) ;lower value
- and.b #$7f,1(a0) ;clear bit 7
- lsr.w #7,d0
- and.b #$7f,d0 ;clr bit 7
- move.b d0,2(a0) ;higher 7 bits
- moveq #3,d0
- bra.w _AddMIDId
-
- mfx_02 lea prevmidipbend-DB(a6),a0
- moveq #0,d1
- move.b trk_prevmidich(a5),d1
- add.b d1,d1
- tst.b d4
- beq.s resetpbend ;x200??
- move.w 0(a0,d1.w),d0
- lsl.w #3,d4
- sub.w d4,d0
- bpl.s bendpitch ;not under 0
- moveq #0,d0
- bra.s bendpitch
- resetpbend: tst.b d3 ;d3 = counter (remember??)
- bne.s mfx_rts
- move.w #$2000,d0
- bra.s bendpitch
- mfx_rts rts
- mfx_13
- mfx_03 tst.b d3
- bne.s mfx_rts
- lea prevmidipbend-DB(a6),a0
- moveq #0,d1
- move.b trk_prevmidich(a5),d1
- add.b d1,d1
- move.b d4,d0
- add.b #128,d0
- lsl.w #6,d0
- bra.s bendpitch
-
- mfx_0d tst.b d3
- bne.s mfx_rts
- lea noteondata+1-DB(a6),a0 ;CHANNEL AFTERTOUCH
- move.b d4,(a0) ;value
- bmi.s mfx_rts
- move.b trk_prevmidich(a5),-(a0)
- or.b #$d0,(a0)
- moveq #2,d0
- bra.w _AddMIDId
-
- mfx_0a tst.b d3
- bne.s mfx_rts
- lea noteondata+2-DB(a6),a0 ;POLYPHONIC AFTERTOUCH
- and.b #$7f,d4
- move.b d4,(a0)
- move.b trk_prevmidin(a5),-(a0)
- ble.s mfx_rts
- move.b trk_prevmidich(a5),-(a0)
- or.b #$A0,(a0)
- moveq #3,d0
- bra.w _AddMIDId
-
- mfx_17 moveq #$07,d0 ;07 = VOLUME
- bra.s pushctrldata
-
- mfx_04 moveq #$01,d0 ;01 = MODULATION WHEEL
- bra.s pushctrldata
-
- mfx_0e moveq #$0a,d0
- pushctrldata tst.b d3 ;do it only once in a note
- bne.s mfx_rts2 ;(when counter = 0)
- pushctrld_nochk lea noteondata+2-DB(a6),a0 ;push "control change" data,
- move.b d4,(a0) ;second databyte
- bmi.s mfx_rts2 ;$0 - $7F only
- move.b d0,-(a0) ;1st databyte
- move.b trk_prevmidich(a5),-(a0) ;MIDI channel
- or.b #$b0,(a0) ;command (B)
- moveq #3,d0
- bra.w _AddMIDId
-
- mfx_05 and.b #$7f,d4 ;set contr. value of curr. MIDI ch.
- move.b trk_prevmidich(a5),d6
- lea midicontrnum-DB(a6),a0
- adda.w d6,a0
- move.b d4,(a0)
- mfx_rts2 rts
-
- mfx_0f cmp.b #$fa,d4 ;hold pedal ON
- bne.s nomffa
- moveq #$40,d0
- moveq #$7f,d4
- bra.s pushctrldata
- nomffa cmp.b #$fb,d4 ;hold pedal OFF
- bne.w fx_0f
- moveq #$40,d0
- moveq #$00,d4
- bra.s pushctrldata
-
- mfx_00 tst.b d4
- beq.s mfx_rts2
- and.b #$7f,d4
- move.b trk_prevmidich(a5),d6
- lea midicontrnum-DB(a6),a0
- move.b 0(a0,d6.w),d0
- bra.s pushctrldata
-
- mfx_10 tst.b d3
- bne.s mfx_rts2
- move.w d4,d0
- bra.w _InitMIDIDump
-
- ; *** Command 3cxx handling
-
- mfx_31 moveq #0,d0
- bra.s mfx_3x
- mfx_32 moveq #sizeof_mcs,d0
- bra.s mfx_3x
- mfx_33 moveq #sizeof_mcs*2,d0
- bra.s mfx_3x
- mfx_34 moveq #sizeof_mcs*3,d0
- bra.s mfx_3x
- mfx_35 moveq #sizeof_mcs*4,d0
- bra.s mfx_3x
- mfx_36 moveq #sizeof_mcs*5,d0
- bra.s mfx_3x
- mfx_37 moveq #sizeof_mcs*6,d0
- bra.s mfx_3x
- mfx_38 moveq #sizeof_mcs*7,d0
- bra.s mfx_3x
- mfx_39 moveq #sizeof_mcs*8,d0
- bra.s mfx_3x
- mfx_3A moveq #sizeof_mcs*9,d0
- bra.s mfx_3x
- mfx_3B moveq #sizeof_mcs*10,d0
- bra.s mfx_3x
- mfx_3C moveq #sizeof_mcs*11,d0
- bra.s mfx_3x
- mfx_3D moveq #sizeof_mcs*12,d0
- bra.s mfx_3x
- mfx_3E moveq #sizeof_mcs*13,d0
- bra.s mfx_3x
- mfx_3F moveq #sizeof_mcs*14,d0
- mfx_3x tst.b d3 ;counter?
- bne.w mcs_notype5
- lea cmd3xsettings-DB(a6),a0
- adda.w d0,a0
- move.w mcs_controller(a0),d1
- move.b mcs_type(a0),d0
- bne.s mcs_notype0
- ; *** MCS type: STD (MSB)
- cmp.w #$7F,d1
- bhi.s 1$
- move.b d1,d0
- bra pushctrld_nochk
- 1$ rts
- mcs_notype0 subq.b #1,d0
- bne.s mcs_notype1
- ; *** MCS type: STD (LSB)
- cmp.w #$7F,d1
- bhi.s 1$
- cmp.w #$1F,d1
- bhi.s 2$
- add.w #$20,d1 ;if contr. num was 0 - 1F, add $20 to get contr. LSB
- 2$ move.b d1,d0
- bra pushctrld_nochk
- 1$ rts
- mcs_notype1 subq.b #1,d0
- bne.s mcs_notype2
- ; *** MCS type: RPN (MSB)
- move.l d2,-(sp)
- move.w d1,d2
- addq.w #1,d2 ;ctrlr num + 1
- lea noteondata-DB(a6),a0
- moveq #0,d0
- move.b trk_prevmidich(a5),d0
- lea prevmidiptype-DB(a6),a1
- bclr #0,0(a1,d0.w) ;test last parameter: RPN or NRPN?, set RPN
- lea prevmidipn-DB(a6),a1 ;load parameter address in A1
- adda.w d0,a1
- adda.w d0,a1
- bne.s 1$ ;NRPN... send full ident
- cmp.w (a1),d2 ;the same parameter number?
- bne.s 1$ ;no.. send param. number
- or.b #$B0,d0
- move.b d0,(a0)+
- moveq #3,d0
- bra.s 2$
- 1$ move.w d2,(a1)
- or.b #$B0,d0
- move.b d0,(a0)+
- move.b #$64,(a0)+ ;RPN LSB
- move.b d1,(a0)
- and.b #$7F,(a0)+ ;lower 7 bits of ctrlr number
- lsr.w #7,d1
- move.b #$65,(a0)+ ;RPN MSB
- move.b d1,(a0)+
- moveq #7,d0
- 2$ move.b #$06,(a0)+ ;data entry, MSB
- move.b d4,(a0)
- lea noteondata-DB(a6),a0
- move.l (sp)+,d2
- bra.w _AddMIDId
- mcs_notype2 subq.b #1,d0
- bne.s mcs_notype3
- ; *** MCS type: RPN (LSB)
- move.l d2,-(sp)
- move.w d1,d2
- addq.w #1,d2 ;ctrlr num + 1
- lea noteondata-DB(a6),a0
- moveq #0,d0
- move.b trk_prevmidich(a5),d0
- lea prevmidiptype-DB(a6),a1
- bclr #0,0(a1,d0.w) ;test last parameter: RPN or NRPN?, set RPN
- lea prevmidipn-DB(a6),a1 ;load parameter address in A1
- adda.w d0,a1
- adda.w d0,a1
- bne.s 1$ ;NRPN... send full ident
- cmp.w (a1),d2 ;the same parameter number?
- bne.s 1$ ;no.. send param. number
- or.b #$B0,d0
- move.b d0,(a0)+
- moveq #3,d0
- bra.s 2$
- 1$ move.w d2,(a1)
- or.b #$B0,d0
- move.b d0,(a0)+
- move.b #$64,(a0)+ ;RPN LSB
- move.b d1,(a0)
- and.b #$7F,(a0)+ ;lower 7 bits of ctrlr number
- lsr.w #7,d1
- move.b #$65,(a0)+ ;RPN MSB
- move.b d1,(a0)+
- moveq #7,d0
- 2$ move.b #$26,(a0)+ ;data entry, LSB
- move.b d4,(a0)
- lea noteondata-DB(a6),a0
- move.l (sp)+,d2
- bra.w _AddMIDId
- mcs_notype3 subq.b #1,d0
- bne.s mcs_notype4
- ; *** MCS type: NRPN (MSB)
- move.l d2,-(sp)
- move.w d1,d2
- addq.w #1,d2 ;ctrlr num + 1
- lea noteondata-DB(a6),a0
- moveq #0,d0
- move.b trk_prevmidich(a5),d0
- lea prevmidiptype-DB(a6),a1
- bset #0,0(a1,d0.w) ;test last parameter: RPN or NRPN?, set NRPN
- lea prevmidipn-DB(a6),a1 ;load parameter address in A1
- adda.w d0,a1
- adda.w d0,a1
- beq.s 1$ ;RPN... send full ident
- cmp.w (a1),d2 ;the same parameter number?
- bne.s 1$ ;no.. send param. number
- or.b #$B0,d0
- move.b d0,(a0)+
- moveq #3,d0
- bra.s 2$
- 1$ move.w d2,(a1)
- or.b #$B0,d0
- move.b d0,(a0)+
- move.b #$62,(a0)+ ;NRPN LSB
- move.b d1,(a0)
- and.b #$7F,(a0)+ ;lower 7 bits of ctrlr number
- lsr.w #7,d1
- move.b #$63,(a0)+ ;NRPN MSB
- move.b d1,(a0)+
- moveq #7,d0
- 2$ move.b #$06,(a0)+ ;data entry, MSB
- move.b d4,(a0)
- lea noteondata-DB(a6),a0
- move.l (sp)+,d2
- bra.w _AddMIDId
- mcs_notype4 subq.b #1,d0
- bne.s mcs_notype5
- ; *** MCS type: NRPN (MSB)
- move.l d2,-(sp)
- move.w d1,d2
- addq.w #1,d2 ;ctrlr num + 1
- lea noteondata-DB(a6),a0
- moveq #0,d0
- move.b trk_prevmidich(a5),d0
- lea prevmidiptype-DB(a6),a1
- bset #0,0(a1,d0.w) ;test last parameter: RPN or NRPN?, set NRPN
- lea prevmidipn-DB(a6),a1 ;load parameter address in A1
- adda.w d0,a1
- adda.w d0,a1
- beq.s 1$ ;RPN... send full ident
- cmp.w (a1),d2 ;the same parameter number?
- bne.s 1$ ;no.. send param. number
- or.b #$B0,d0
- move.b d0,(a0)+
- moveq #3,d0
- bra.s 2$
- 1$ move.w d2,(a1)
- or.b #$B0,d0
- move.b d0,(a0)+
- move.b #$62,(a0)+ ;NRPN LSB
- move.b d1,(a0)
- and.b #$7F,(a0)+ ;lower 7 bits of ctrlr number
- lsr.w #7,d1
- move.b #$63,(a0)+ ;NRPN MSB
- move.b d1,(a0)+
- moveq #7,d0
- 2$ move.b #$26,(a0)+ ;data entry, MSB
- move.b d4,(a0)
- lea noteondata-DB(a6),a0
- move.l (sp)+,d2
- bra.w _AddMIDId
- mcs_notype5 rts
-
-
- _ResetMIDI: movem.l d2/a2/a6,-(sp)
- movea.l 4.w,a6 ;ExecBase
- jsr -$78(a6) ;Disable()
- lea DB,a6
- ; Clear preset memory
- lea prevmidicpres-DB(a6),a0
- moveq #7,d2
- RM_loop0 clr.l (a0)+ ;force presets to be set again
- dbf d2,RM_loop0
- clr.b lastcmdbyte
- ; Reset pitchbenders & modulation wheels
- lea midiresd-DB(a6),a2
- move.b #$e0,(a2)
- move.b #$b0,3(a2)
- moveq #15,d2
- respbendl: movea.l a2,a0
- moveq #6,d0
- bsr.w _AddMIDId
- addq.b #1,(a2)
- addq.b #1,3(a2)
- dbf d2,respbendl
- lea prevmidipbend-DB(a6),a2
- moveq #15,d2
- 1$ move.w #$2000,(a2)+
- dbf d2,1$
- ; Clear parameters (set to undefined)
- lea prevmidipn-DB(a6),a2
- lea prevmidiptype-DB(a6),a0
- moveq #15,d2
- 2$ clr.w (a2)+
- clr.b (a0)+
- dbf d2,2$
- ; Clear dump variables
- clr.b sysx-DB(a6)
- lea dumpqueue-DB(a6),a0
- move.l a0,dqreadptr-DB(a6)
- move.l a0,dqwriteptr-DB(a6)
- clr.w dqentries-DB(a6)
- ; Enable & exit
- movea.l 4.w,a6
- jsr -$7e(a6) ;Enable()
- movem.l (sp)+,d2/a2/a6
- rts
- ENDC
-
- ; *************************************************************************
- ; *************************************************************************
- ; *********** P U B L I C F U N C T I O N S ***********
- ; *************************************************************************
- ; *************************************************************************
-
- XDEF _InitModuleM,_PlayModuleM
- XDEF _InitPlayerM,_RemPlayerM,_StopPlayerM
- XDEF _ContModuleM
-
- ; *************************************************************************
- ; InitModule(a0 = module) -- extract expansion data etc.. from a module
- ; *************************************************************************
-
- _InitModuleM: movem.l a2-a3/d2,-(sp)
- move.l a0,-(sp)
- beq IM_exit ;0 => xit
- IFNE RELVOL
- movea.l mmd_songinfo(a0),a1 ;MMD0song
- move.b msng_mastervol(a1),d0 ;d0 = mastervol
- ext.w d0
- lea trackdataptrs,a2
- cmp.b #'2',3(a0) ;MMD2?
- bcs.s IM_mmd01
- move.w msng_numtracks(a1),d1
- subq.w #1,d1
- movea.l msng_trkvoltbl(a1),a1
- bra.s IM_loop0
- IM_mmd01 lea msng_trkvol(a1),a1 ;a1 = trkvol
- moveq #MAX_MMD1_TRACKS-1,d1
- IM_loop0 move.b (a1)+,d2 ;get vol...
- ext.w d2
- move.l (a2)+,a3 ;pointer to track data
- mulu d0,d2 ;mastervol * trackvol
- lsr.w #4,d2
- move.w d2,trk_trackvol(a3)
- dbf d1,IM_loop0
- ENDC
- IFNE SYNTH
- lea trackdataptrs,a2
- moveq #63,d1
- IM_loop1 move.l (a2)+,a3
- clr.l trk_synthptr(a3)
- clr.b trk_synthtype(a3)
- dbf d1,IM_loop1
- ENDC
- lea holdvals,a2
- movea.l a0,a3
- move.l mmd_expdata(a0),d0 ;expdata...
- beq IM_clrhlddec ;none here
- move.l d0,a1
- move.l 4(a1),d0 ;exp_smp
- beq IM_clrhlddec ;again.. nothing
- move.l d0,a0 ;InstrExt...
- move.w 8(a1),d2 ;# of entries
- beq IM_clrhlddec
- ; perhaps >63 instruments are supported in the future... just in case...
- cmp.w #63,d2
- ble.s 1$
- moveq #63,d2
- 1$ move.l a4,-(sp)
- lea rptrptlen,a4
- subq.w #1,d2 ;-1 (for dbf)
- move.w 10(a1),d0 ;entry size
- movea.l mmd_songinfo(a3),a3 ;MMD0song
- IFNE MIDI
- lea 4*63(a2),a1 ;pointer to ext_midipsets...
- ENDC
- IM_loop2 clr.b 2*63(a2) ;clear finetune
- cmp.w #3,d0
- ble.s IM_noftune
- move.b 3(a0),126(a2) ;InstrExt.finetune -> finetune
- IM_noftune clr.b 3*63(a2) ;clear flags
- cmp.w #6,d0
- blt.s IM_noflags
- move.b 5(a0),3*63(a2) ;InstrExt.flags -> flags
- bra.s IM_gotflags
- IM_noflags cmp.w #1,inst_replen(a3)
- bls.s IM_gotflags
- bset #0,3*63(a2)
- IM_gotflags clr.b 6*63(a2) ;Initally OUTPUT_STD
- cmp.w #9,d0
- blt.s IM_noopdev
- move.b 8(a0),6*63(a2) ;get InstrExt.output_device
- IM_noopdev cmp.w #18,d0
- blt.s IM_nolongrpt
- move.l 10(a0),(a4)+ ;rpt
- move.l 14(a0),(a4)+ ;rptlen
- bra.s IM_gotlongrpt
- IM_nolongrpt moveq #0,d1
- move.w inst_repeat(a3),d1
- add.l d1,d1
- move.l d1,(a4)+
- moveq #0,d1
- move.w inst_replen(a3),d1
- add.l d1,d1
- move.l d1,(a4)+
- IM_gotlongrpt
- IFNE MIDI
- cmp.w #2,d0
- ble.s IM_nsmnoff
- tst.b 2(a0) ;suppress MIDI note off?
- beq.s IM_nsmnoff
- bset #7,inst_midich(a3)
- IM_nsmnoff move.b inst_midipreset(a3),d1
- ext.w d1
- move.w d1,(a1)
- cmp.w #8,d0
- ble.s IM_nolongpset
- move.w 6(a0),(a1) ;-> ext_midipsets
- btst #1,5(a0)
- beq.s IM_nolongpset
- bset #6,inst_midich(a3)
- IM_nolongpset addq.l #2,a1
- ENDC
- move.b 1(a0),63(a2) ;InstrExt.decay -> decay
- move.b (a0),(a2)+ ;InstrExt.hold -> holdvals
- adda.w d0,a0 ;ptr to next InstrExt
- addq.l #8,a3 ;next instrument...
- dbf d2,IM_loop2
- move.l (sp)+,a4
- bra.s IM_exit
- IM_clrhlddec move.w #5*63+2*63+4*126-1,d0 ;no InstrExt => clear holdvals/decays
- 1$ clr.b (a2)+ ;..and finetunes/flags/ext_psets etc..
- dbf d0,1$
- movea.l (sp),a0
- ; -------- For (very old) MMDs, with no InstrExt, set flags/SSFLG_LOOP,
- ; -------- also copy inst_midipreset to ext_midipsets.
- movea.l mmd_songinfo(a0),a3
- lea flags,a2
- lea rptrptlen,a0
- IFNE MIDI
- lea ext_midipsets,a1
- ENDC
- moveq #62,d0
- IM_loop4 cmp.w #1,inst_replen(a3)
- bls.s IM_noreptflg
- bset #0,(a2)
- IM_noreptflg addq.l #1,a2
- IFNE MIDI
- move.b inst_midipreset(a3),d1
- ext.w d1
- move.w d1,(a1)+
- ENDC
- moveq #0,d1
- move.w inst_repeat(a3),d1
- add.l d1,d1
- move.l d1,(a0)+
- move.w inst_replen(a3),d1
- add.l d1,d1
- move.l d1,(a0)+
- addq.l #8,a3 ;next inst
- dbf d0,IM_loop4
- IM_exit
- ; -------- Get MIDI command 3x settings (if they exist)
- IFNE MIDI
- movea.l (sp),a0
- lea cmd3xsettings,a2
- move.l mmd_expdata(a0),d0
- beq.s IM_c3_clr
- move.l d0,a0
- move.l 64(a0),d0 ;mmdcmd3x
- beq.s IM_c3_clr
- move.w 2(a0),d0 ;num_of_settings
- cmp.w #15,d0
- bhi.s 1$
- moveq #15,d0
- 1$ move.l 4(a0),d1 ;ctrlr types
- beq.s IM_c3_clr
- movea.l d1,a1
- move.l 8(a0),d1 ;ctrlr numbers
- beq.s IM_c3_clr
- movea.l d1,a3
- subq.w #1,d0
- bmi.s IM_c3_clr
- 2$ move.b (a1)+,d1
- ext.w d1
- move.w d1,(a2)+
- move.w (a3)+,(a2)+
- dbra d0,2$
- bra.s IM_c3_exit
- IM_c3_clr moveq #15-1,d0
- 1$ clr.l (a2)+
- dbra d0,1$
- IM_c3_exit
- ENDC
- ; -------- Exit
- addq.l #4,sp
- movem.l (sp)+,a2-a3/d2
- rts
- ; *************************************************************************
- ; InitPlayerM() -- allocate interrupt, audio, serial port etc...
- ; *************************************************************************
- _InitPlayerM:
- IFNE MIDI
- bsr.w _GetSerial
- tst.l d0
- bne.s IP_error
- ENDC
- bsr.w _AudioInit
- tst.l d0
- bne.s IP_error
- rts
- IP_error bsr.s _RemPlayerM
- moveq #-1,d0
- rts
- ; *************************************************************************
- ; RemPlayerM() -- free interrupt, audio, serial port etc..
- ; *************************************************************************
- _RemPlayerM: movem.l a5/a6,-(sp)
- lea DB,a5
- tst.b audiodevopen-DB(a5)
- beq.s RP_notimer ;timer is not ours
- bsr.s _StopPlayerM
- bsr.w FreeMixBuffers
- clr.w _mix_channels-DB(a5)
- movea.l 4.w,a6 ;ExecBase
- jsr -$78(a6) ;Disable()
- movea.l _chinfo-DB(a5),a1
- clr.l _chinfo-DB(a5)
- jsr -$2B2(a6) ;FreeVec
- movea.l _voltable-DB(a5),a1
- clr.l _voltable-DB(a5)
- jsr -$2B2(a6) ;FreeVec
- jsr -$7E(a6) ;Enable()
- movea.l _frqtblmem-DB(a5),a1
- clr.l _frqtblmem-DB(a5)
- jsr -$2B2(a6) ;FreeVec
- RP_notimer: bsr.w _AudioRem
- IFNE MIDI
- bsr.w _FreeSerial
- ENDC
- movem.l (sp)+,a5/a6
- rts
- ; *************************************************************************
- ; StopPlayerM() -- stop the music
- ; *************************************************************************
- _StopPlayerM: move.l a6,-(sp)
- lea DB,a6
- tst.b audiodevopen-DB(a6)
- beq.s SP_end ;res. alloc fail.
- bsr.w StopMix
- move.l _module-DB(a6),d0
- beq.s SP_nomod
- move.l d0,a0
- clr.w mmd_pstate(a0)
- clr.l _module-DB(a6)
- SP_nomod
- IFNE MIDI
- clr.b lastcmdbyte-DB(a6)
- ENDC
- bsr.w SoundOff
- SP_end movea.l (sp)+,a6
- rts
-
-
- _ContModuleM tst.b audiodevopen
- beq.s SP_end
- move.l a0,-(sp)
- bsr.w SoundOff
- move.l (sp)+,a0
- moveq #0,d0
- bra.s contpoint
- ; *************************************************************************
- ; PlayModuleM(a0 = module) -- initialize & play it!
- ; *************************************************************************
- _PlayModuleM: st d0
- contpoint movem.l a0/d0,-(sp)
- bsr _InitModuleM
- movem.l (sp)+,a0/d0
- movem.l a4/a6,-(sp)
- lea DB,a6
- tst.b audiodevopen-DB(a6)
- beq PM_err ;resource allocation failure
- move.l a0,d1
- beq PM_err ;module failure
- clr.l _module-DB(a6)
- IFNE MIDI
- clr.b lastcmdbyte-DB(a6)
- ENDC
- move.w _modnumm,d1
- beq.s PM_modfound
- PM_nextmod tst.l mmd_expdata(a0)
- beq.s PM_modfound
- move.l mmd_expdata(a0),a1
- tst.l (a1)
- beq.s PM_modfound ;no more modules here!
- move.l (a1),a0
- subq.w #1,d1
- bgt.s PM_nextmod
- PM_modfound cmp.b #'T',3(a0)
- bne.s PM_nomodT
- move.b #'0',3(a0) ;change MCNT to MCN0
- PM_nomodT movea.l mmd_songinfo(a0),a1 ;song
- move.l a1,_sng_struct-DB(a6)
- movea.l a1,a4
- move.b msng_tempo2(a1),mmd_counter(a0) ;init counter
- tst.b msng_flags2(a1)
- bpl.w PM_err ;does not use mixing... FAIL!
- btst #0,msng_flags(a1)
- bne.s PM_filon
- bset #1,$bfe001
- bra.s PM_filset
- PM_filon bclr #1,$bfe001
- PM_filset tst.b d0
- beq.s PM_noclr
- clr.l mmd_pline(a0)
- clr.l rptline-DB(a6)
- clr.w blkdelay-DB(a6)
- ; ---------- Set 'pblock' and 'pseq' to correct values...
- PM_noclr move.w mmd_psecnum(a0),d1
- move.l a2,-(sp) ;need extra register
- movea.l msng_sections(a1),a2
- add.w d1,d1
- move.w 0(a2,d1.w),d1 ;get sequence number
- add.w d1,d1
- add.w d1,d1
- move.w d1,mmd_pseq(a0)
- movea.l msng_pseqs(a1),a2
- movea.l 0(a2,d1.w),a2 ;PlaySeq...
- move.w mmd_pseqnum(a0),d1
- add.w d1,d1
- move.w 42(a2,d1.w),d1 ;and the correct block..
- move.l (sp)+,a2
- move.w d1,mmd_pblock(a0)
- move.w #-1,mmd_pstate(a0)
- move.l a0,_module-DB(a6)
- bsr.w InitMix
- tst.l d0
- bne.s PM_err
- move.l d2,-(sp)
- moveq #0,d2
- move.b _mix14bit-DB(a6),d2
- XREF _StartAmigaMix
- jsr _StartAmigaMix(pc)
- move.l (sp)+,d2
- moveq #0,d0
- movem.l (sp)+,a4/a6
- rts
- PM_err moveq #1,d0
- movem.l (sp)+,a4/a6
- rts
- ; *************************************************************************
-
- _AudioInit: movem.l a4/a6/d3,-(sp)
- lea DB,a4
- movea.l 4.w,a6
- lea utilityname-DB(a4),a1
- moveq #0,d0
- jsr -$228(a6) ;OpenLibrary()
- move.l d0,UtBase
- beq.s initerr
- ; +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ alloc signal bit
- IFNE AUDDEV
- moveq #-1,d0
- jsr -$14a(a6) ;AllocSignal()
- tst.b d0
- bmi.s initerr
- move.b d0,sigbitnum-DB(a4)
- ; +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ prepare IORequest
- lea allocport-DB(a4),a1
- move.b d0,15(a1) ;set mp_SigBit
- move.l a1,-(sp)
- suba.l a1,a1
- jsr -$126(a6) ;FindTask(0)
- move.l (sp)+,a1
- move.l d0,16(a1) ;set mp_SigTask
- lea reqlist-DB(a4),a0
- move.l a0,(a0) ;NEWLIST begins...
- addq.l #4,(a0)
- clr.l 4(a0)
- move.l a0,8(a0) ;NEWLIST ends...
- ; +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ open audio.device
- lea allocreq-DB(a4),a1
- lea audiodevname-DB(a4),a0
- moveq #0,d0
- moveq #0,d1
- movea.l 4.w,a6
- jsr -$1bc(a6) ;OpenDevice()
- tst.b d0
- bne.w initerr
- ENDC
- st audiodevopen-DB(a4)
- moveq #0,d0
- initret: movem.l (sp)+,a4/a6/d3
- rts
- initerr: moveq #1,d0
- bra.s initret
-
- _AudioRem: movem.l a5-a6,-(sp)
- lea DB,a5
- movea.l 4.w,a6
- move.l UtBase,d0
- beq.s 1$
- move.l d0,a1
- jsr -$19E(a6) ;CloseLibrary
- clr.l UtBase
- 1$
- IFNE AUDDEV
- tst.b audiodevopen-DB(a5)
- beq.s rem2
- move.w #$000f,$dff096 ;stop audio DMA
- ; +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ close audio.device
- lea allocreq-DB(a5),a1
- jsr -$1c2(a6) ;CloseDevice()
- clr.b audiodevopen-DB(a5)
- rem2: moveq #0,d0
- move.b sigbitnum-DB(a5),d0
- bmi.s rem3
- ; +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ free signal bit
- jsr -$150(a6) ;FreeSignal()
- st sigbitnum-DB(a5)
- rem3:
- ENDC
- movem.l (sp)+,a5-a6
- rts
-
- InitFreqTables movem.l a2-a3/d2/a6,-(sp)
- move.l #6*12*2*16,d0
- moveq #1,d1 ;MEMF_PUBLIC
- movea.l 4.w,a6
- jsr -$2AC(a6) ;AllocVec
- move.l d0,_frqtblmem
- beq.s ift_err
- lea _freq_tables,a2
- movea.l d0,a3
- moveq #0,d2
- 1$ move.l a3,(a2)+
- move.l d2,d0
- subq.l #8,d0
- movea.l UtBase,a0
- move.l #509916,d1 ;finetune difference
- jsr -$8A(a0) ;SMult32()
- add.l #68583572,d0 ;C-1 freq * 65536
- movea.l a3,a0
- move.w $128(a6),d1 ;SysBase->AttnFlags
- btst #4,d1 ;68881?
- beq.s 2$
- XREF _FillFreqTable_FP
- jsr _FillFreqTable_FP(pc)
- bra.s 3$
- 2$ move.l #69433,d1 ;12th root of 2 * 65536
- XREF _FillFreqTable
- jsr _FillFreqTable(pc)
- 3$ lea 6*12*2(a3),a3
- addq.l #1,d2
- cmp.w #16,d2
- blt.s 1$
- ift_end moveq #0,d0
- movem.l (sp)+,a2-a3/d2/a6
- rts
- ift_err moveq #1,d0
- movem.l (sp)+,a2-a3/d2/a6
- rts
-
- ; DB in A6
- FillVolTables movem.l d2-d5,-(sp)
- tst.l _voltable-DB(a6)
- beq.s fvt_crtnew
- move.w msng_channels(a4),d0
- cmp.w _prevnumch-DB(a6),d0
- bne.s fvt_crtnew
- move.w msng_voladj(a4),d0
- cmp.w _prevadj-DB(a6),d0
- bne.s fvt_crtnew
- move.l msng_flags3(a4),d0
- move.l d0,d1
- and.b #1,d0 ;get FLAG3_STEREO
- cmp.b _prevstereo-DB(a6),d0
- bne.s fvt_crtnew
- and.b #2,d1 ;get FLAG3_FREEPAN
- cmp.b _prevfreepan-DB(a6),d1
- beq.w fvt_end
- fvt_crtnew tst.l _voltable-DB(a6)
- bne.s 1$
- move.l #64*256*2,d0
- moveq #1,d1 ;MEMF_PUBLIC
- move.l a6,d5
- movea.l 4.w,a6
- jsr -$2AC(a6) ;AllocVec
- move.l d5,a6
- move.l d0,_voltable-DB(a6)
- beq.w fvt_err
- 1$ move.w msng_channels(a4),d2
- move.w d2,_prevnumch-DB(a6)
- move.w msng_voladj(a4),_prevadj-DB(a6)
- move.l msng_flags3(a4),d0
- move.l d0,d1
- and.b #1,d0 ;stereo
- move.b d0,_prevstereo-DB(a6)
- and.b #2,d1 ;freepan
- move.b d1,_prevfreepan-DB(a6)
- ; if(sng->sg->mix_stereo && !sng->sg->mix_freepan && numch > 1) numch /= 2;
- tst.b d0
- beq.s fvt_nohalf
- tst.b d1
- bne.s fvt_nohalf
- cmp.w #1,d2
- ble.s fvt_nohalf
- lsr.w #1,d2
- fvt_nohalf
- ; fill volume table
- mulu #6400,d2
- movea.l _voltable-DB(a6),a0 ;destination
- movea.l UtBase-DB(a6),a1
- moveq #0,d3 ;volcnt
- fvt_outloop moveq #0,d4 ;svalcnt
- move.w d3,d5
- addq.w #1,d5 ;volcnt + 1...
- mulu msng_voladj(a4),d5 ;* adj
- fvt_inloop move.b d4,d0
- lsl.w #8,d0
- muls d5,d0
- move.l d2,d1
- jsr -$96(a1) ;SDivMod32()
- move.w d0,(a0)+
- addq.w #1,d4
- cmp.w #256,d4
- blt.s fvt_inloop
- addq.w #1,d3
- cmp.w #64,d3
- blt.s fvt_outloop
- ; channel shift:
- moveq #0,d5 ;newchshift
- move.w msng_channels(a4),d0
- cmp.w #2,d0
- blo.s 1$
- beq.s 2$
- addq.w #2,d5
- cmp.w #4,d0
- bls.s 1$
- addq.w #1,d5
- cmp.w #8,d0
- bls.s 1$
- addq.w #1,d5
- cmp.w #16,d0
- bls.s 1$
- addq.w #1,d5
- cmp.w #32,d0
- bls.s 1$
- 2$ addq.w #1,d5
- 1$ btst #0,msng_flags3+3(a4)
- beq.s fvt_nostrshft
- btst #1,msng_flags3+3(a4)
- bne.s fvt_nostrshft
- tst.w d5
- beq.s fvt_nostrshft
- subq.w #1,d5
- fvt_nostrshft move.w msng_voladj(a4),d1
- ; test vol adj. above 100
- tst.w d5
- beq.s fvt_noabvol
- cmp.w #200,d1
- blo.s fvt_noabvol
- subq.w #1,d5
- beq.s fvt_noabvol
- cmp.w #400,d1
- blo.s fvt_noabvol
- subq.w #1,d5
- beq.s fvt_noabvol
- cmp.w #800,d1
- blo.s fvt_noabvol
- subq.w #1,d5
- fvt_noabvol
- ; test vol adj. below 100
- cmp.w #100,d1
- bhs.s fvt_nobevol
- addq.w #1,d5
- cmp.w #50,d1
- bhs.s fvt_nobevol
- addq.w #1,d5
- cmp.w #25,d1
- bhs.s fvt_nobevol
- addq.w #1,d5
- cmp.w #13,d1
- bhs.s fvt_nobevol
- addq.w #1,d5
- cmp.w #7,d1
- bhs.s fvt_nobevol
- addq.w #1,d5
- cmp.w #4,d1
- bhs.s fvt_nobevol
- addq.w #1,d5
- cmp.w #2,d1
- bhs.s fvt_nobevol
- addq.w #1,d5
- fvt_nobevol move.w d5,_chshift-DB(a6)
- fvt_end moveq #0,d0
- movem.l (sp)+,d2-d5
- rts
- fvt_err moveq #1,d0
- movem.l (sp)+,d2-d5
- rts
-
- ; DB in A6
- AllocEchoBuffer ;echo length in d0
- movem.l d2/d3,-(sp)
- move.w _actualrate_hz-DB(a6),d1
- mulu d1,d0
- movea.l UtBase-DB(a6),a0
- moveq #0,d1
- move.w #1000,d1
- jsr -$9c(a0) ;UDivMod32()
- move.l d0,d2 ;ebsz
- move.l d2,d3
- add.l d3,d3 ;actsz
- btst #FLAG3B_STEREO,msng_flags3+3(a4)
- beq.s 1$
- add.l d3,d3
- 1$ move.l d3,d0
- moveq #1,d1 ;PUBLIC
- bset #16,d1 ;CLEAR
- move.l a6,d3
- movea.l 4.w,a6
- jsr -$2AC(a6) ;AllocVec
- move.l d3,a6
- move.l d0,_echobuffer-DB(a6)
- move.l d2,_echobuffsz-DB(a6)
- clr.l _echord-DB(a6)
- movem.l (sp)+,d2/d3
- rts
-
- ; DB in A6
- FreeEchoBuffer move.l a6,-(sp)
- move.l _echobuffer-DB(a6),a1
- clr.l _echobuffer-DB(a6)
- movea.l 4.w,a6
- jsr -$2B2(a6) ;FreeVec
- move.l (sp)+,a6
- rts
-
- ; DB in A6
- AllocMixBuffers movem.l d2/a2/a3/a6,-(sp)
- movea.l a6,a3
- moveq #2,d2 ;number of chip mem buffers
- btst #FLAG3B_STEREO,msng_flags3+3(a4)
- beq.s 1$
- add.l d2,d2 ;stereo... two buffers
- 1$ tst.b _mix14bit-DB(a3)
- beq.s 2$
- add.l d2,d2 ;14bit... 4/8 buffers
- 2$ lea _chipbuff-DB(a3),a2
- movea.l 4.w,a6
- subq.w #1,d2
- 3$ move.l _mixbuffsize-DB(a3),d0
- moveq #3,d1 ;CHIP, PUBLIC
- bset #16,d1 ;CLEAR
- jsr -$2AC(a6) ;AllocVec
- move.l d0,(a2)+
- beq.s amb_err
- dbra d2,3$
- move.l _mixbuffsize-DB(a3),d0
- add.l d0,d0
- btst #FLAG3B_STEREO,msng_flags3+3(a4)
- beq.s 4$
- add.l d0,d0
- 4$ move.l d0,d2
- moveq #1,d1 ;PUBLIC
- bset #16,d1 ;CLEAR
- jsr -$2AC(a6) ;AllocVec
- move.l d0,_mixbuff-DB(a3)
- beq.s amb_err
- move.l d2,d0
- moveq #1,d1 ;PUBLIC
- bset #16,d1 ;CLEAR
- jsr -$2AC(a6) ;AllocVec
- move.l d0,_mixbuff+4-DB(a3)
- beq.s amb_err
- move.l _mixbuffsize-DB(a3),_buffsize-DB(a3)
- movem.l (sp)+,d2/a2/a3/a6
- moveq #0,d0
- rts
- amb_err bsr.s FreeMixBuffers
- movem.l (sp)+,d2/a2/a3/a6
- moveq #1,d0
- rts
-
- FreeMixBuffers movem.l a2/a3/d2/a6,-(sp)
- lea DB,a3
- moveq #7,d2
- lea _chipbuff-DB(a3),a2
- movea.l 4.w,a6
- 1$ move.l (a2),a1
- clr.l (a2)+
- jsr -$2B2(a6) ;FreeVec
- dbra d2,1$
- move.l _mixbuff-DB(a3),a1
- jsr -$2B2(a6) ;FreeVec
- move.l _mixbuff+4-DB(a3),a1
- jsr -$2B2(a6) ;FreeVec
- clr.l _mixbuff-DB(a3)
- clr.l _mixbuff+4-DB(a3)
- clr.l _buffsize-DB(a3)
- movem.l (sp)+,a2/a3/d2/a6
- rts
-
- ; InitMix... song ptr in A4, DB in A6
- InitMix: move.l a6,-(sp)
- bsr AllocMixBuffers
- tst.l d0
- bne.w initm_err
- clr.w _currleft
- clr.w _currleftfract
- bsr InitFreqTables
- tst.l d0
- bne.w initm_err
- ; --- set audio hardware
- lea $DFF000,a0
- move.w #$0780,$9A(a0) ;INTENA
- move.w #$F,$96(a0) ;DMACON
- move.l #3579545,d0
- move.l _mixfreq-DB(a6),d1
- divu d1,d0 ;d0 = period
- move.l _buffsize-DB(a6),d1
- lsr.l #1,d1 ;d1 = buffer length
- move.w d1,$A4(a0)
- move.w d1,$B4(a0)
- move.w d1,$C4(a0)
- move.w d1,$D4(a0)
- move.w d0,$A6(a0)
- move.w d0,$B6(a0)
- move.w d0,$C6(a0)
- move.w d0,$D6(a0)
- moveq #64,d1
- move.w d1,$A8(a0)
- move.w d1,$B8(a0)
- tst.b _mix14bit-DB(a6)
- beq.s 5$
- moveq #1,d1
- 5$ move.w d1,$C8(a0)
- move.w d1,$D8(a0)
- move.l #3579545,d1
- divu d0,d1
- move.w d1,_actualrate_hz-DB(a6)
- move.w d1,d0
- clr.w d1
- divu d0,d1
- move.w d1,_actualrate_fract-DB(a6)
- ; --- allocate channel structures (if not already allocated)
- move.w msng_channels(a4),d0
- bne.s 4$
- moveq #4,d0 ;0 -> 4
- 4$ cmp.w _mix_channels-DB(a6),d0
- beq.s 1$
- movea.l a6,a0
- move.l a6,-(sp)
- movea.l 4.w,a6 ;ExecBase
- jsr -$78(a6) ;Disable()
- movea.l _chinfo-DB(a0),a1
- clr.l _chinfo-DB(a0)
- jsr -$7E(a6) ;Enable()
- clr.w _mix_channels-DB(a0)
- mulu #ci_sizeof,d0
- moveq #1,d1 ;MEMF_PUBLIC
- jsr -$2AC(a6) ;AllocVec
- movea.l (sp)+,a6
- move.l d0,_chinfo-DB(a6)
- beq.s initm_err
- move.w msng_channels(a4),_mix_channels-DB(a6)
- bne.s 1$
- move.w #4,_mix_channels-DB(a6)
- 1$ move.w _mix_channels-DB(a6),d0
- mulu #ci_sizeof,d0
- movea.l _chinfo-DB(a6),a1
- movea.l a1,a0
- subq.w #1,d0
- 2$ clr.b (a1)+
- dbra d0,2$
- move.w _mix_channels-DB(a6),d0
- subq.w #1,d0
- 3$ bset #CHFLAGB_MUTED,ci_flags(a0)
- bset #CHFLAGB_STARTSYN,ci_flags(a0)
- lea ci_sizeof(a0),a0
- dbra d0,3$
- bsr.w FillVolTables
- tst.l d0
- bne.s initm_err
- XREF _SetMixVars
- jsr _SetMixVars(pc)
- movea.l a4,a0
- jsr _SetMixTempo(pc)
- tst.b msng_m_echo(a4)
- beq.s initm_noecho
- cmp.b #2,msng_m_echo(a4)
- bhi.s initm_noecho ;unknown echo type!
- moveq #0,d0
- move.w msng_m_echolen(a4),d0
- bsr.w AllocEchoBuffer
- initm_noecho move.l (sp)+,a6
- moveq #0,d0
- rts
- initm_err bsr.s StopMix
- move.l (sp)+,a6
- moveq #1,d0
- rts
-
- StopMix: move.w #$0080,$DFF09A ;INTENA = INTF_AUD0
- move.w #$F,$DFF096 ;stop audio DMA
- bsr.w FreeMixBuffers
- bra.w FreeEchoBuffer
-
- IFNE MIDI
- _GetSerial: movem.l a5-a6,-(sp) ;Get serial port for MIDI
- lea DB,a5
- bsr.s GetSer2
- tst.l d0 ;got the port??
- beq.s rgser ;yes
- movea.l 4.w,a6 ;no..try to flush serial.device:
- jsr -$84(a6) ;Forbid
- lea $15e(a6),a0 ;ExecBase->DeviceList
- lea serdev-DB(a5),a1 ;"serial.device"
- jsr -$114(a6) ;FindName
- tst.l d0
- beq.s serdnotf ;no serial.device!!
- move.l d0,a1
- jsr -$1b6(a6) ;RemDevice
- serdnotf: jsr -$8a(a6) ;and Permit
- bsr.s GetSer2 ;now try it again...
- rgser: movem.l (sp)+,a5-a6
- rts
-
- GetSer2: movea.l 4.w,a6
- moveq #0,d0
- lea miscresname-DB(a5),a1
- jsr -$1f2(a6) ;OpenResource()
- move.l d0,miscresbase-DB(a5)
- tst.l d0
- beq.s gserror
- move.l d0,a6
- lea medname-DB(a5),a1
- moveq #0,d0 ;serial port
- jsr -$6(a6) ;AllocMiscResource()
- tst.l d0
- bne.s gserror
- lea medname-DB(a5),a1
- moveq #1,d0 ;serial bits
- jsr -$6(a6)
- tst.l d0
- beq.s gs2_allocok
- moveq #0,d0
- jsr -$c(a6) ;bits failed -> Free serial port
- bra.s gserror
- gs2_allocok move.w $dff01c,d0
- btst #0,d0
- sne intrson-DB(a5)
- moveq #0,d0 ;TBE
- lea serinterrupt-DB(a5),a1
- move.l 4.w,a6
- jsr -$a2(a6) ;SetIntVector()
- move.l d0,prevtbe-DB(a5)
- move.w #$8001,$dff09a ;TBE on
- move.w #114,$dff032 ;set baud rate (SERPER)
- st serportalloc-DB(a5)
- moveq #0,d0
- rts
- gserror: moveq #-1,d0
- rts
-
- _FreeSerial: movem.l a5-a6,-(sp)
- lea DB,a5
- tst.l miscresbase-DB(a5)
- beq.s retfs
- tst.b serportalloc-DB(a5)
- beq.s retfs
- wmb_loop move.w $dff018,d0 ;WAIT until all data sent
- btst #12,d0 ;test TSRE bit of SERDAT
- beq.s wmb_loop
- move.w #$0001,$dff09a ;disable TBE
- movea.l 4.w,a6
- move.l prevtbe-DB(a5),a1
- moveq #0,d0
- jsr -$a2(a6) ;SetIntVector()
- fs_noptbe movea.l miscresbase-DB(a5),a6
- moveq #0,d0 ;serial port
- jsr -$c(a6) ;FreeMiscResource()
- moveq #1,d0 ;serial bits
- jsr -$c(a6)
- clr.b serportalloc-DB(a5)
- clr.b lastcmdbyte-DB(a5)
- retfs: movem.l (sp)+,a5-a6
- rts
-
- ; Message number in d0.
- _InitMIDIDump: tst.b serportalloc
- beq.s idd_rts
- movem.l a1/a5/a6,-(sp) ;a1 = data pointer, d1 = length
- lea DB,a5
- movea.l 4.w,a6 ;ExecBase
- jsr -$78(a6) ;Disable()
- cmp.w #16,dqentries-DB(a5) ;dump queue full?
- bge.s idd_exit ;exit without doing anything
- lea dqwriteptr-DB(a5),a1
- movea.l (a1),a0
- move.w d0,(a0)+ ;store message number
- cmpa.l a1,a0 ;queue end?
- bne.s idd_noresetbuff
- lea dumpqueue-DB(a5),a0 ;reset write pointer
- idd_noresetbuff move.l a0,(a1) ;and write it back.
- addq.w #1,dqentries-DB(a5)
- tst.b sysx-DB(a5) ;already sending data?
- bne.s idd_exit ;yes. Don't initiate new send.
- clr.b lastcmdbyte-DB(a5)
- bsr StartNewDump
- move.w $dff018,d0 ;SERDATR
- btst #13,d0
- beq.s idd_exit
- move.w #$8001,$dff09c ;request TBE
- idd_exit jsr -$7e(a6) ;Enable()
- movem.l (sp)+,a1/a5/a6
- idd_rts rts
-
- SerIntHandler: move.w #$4000,$9a(a0) ;disable..(Interrupts are enabled anyway)
- move.w #1,$9c(a0) ;clear intreq bit
- tst.b sysx-buffptr(a1) ;sysx??
- bne.s sih_sysx
- move.w bytesinbuff-buffptr(a1),d0 ;bytesinbuff
- beq.s exsih ;buffer empty
- movea.l readbuffptr-buffptr(a1),a5 ;get buffer read pointer
- move.w #$100,d1 ;Stop bit
- move.b (a5)+,d1 ;get byte
- move.w d1,$30(a0) ;and push it to SERDAT
- cmpa.l a1,a5 ;shall we reset ptr?
- bne.s norrbuffptr ;not yet..
- lea -256(a1),a5
- norrbuffptr subq.w #1,d0 ;one less bytes in buffer
- move.w d0,bytesinbuff-buffptr(a1) ;remember it
- move.l a5,readbuffptr-buffptr(a1) ;push new read ptr back
- exsih move.w #$c000,$9a(a0)
- rts
- sih_sysx move.w #$100,d1
- movea.l sysxptr-buffptr(a1),a5 ;data pointer
- move.b (a5)+,d1
- move.l a5,sysxptr-buffptr(a1)
- move.w d1,$30(a0) ;-> SERDAT
- subq.l #1,sysxleft-buffptr(a1) ;sub data left length
- bne.s exsih ;not 0w
- lea DB,a5
- clr.b lastcmdbyte-DB(a5)
- bsr.s StartNewDump
- bra.s exsih
-
- StartNewDump: tst.w dqentries-DB(a5) ;queue empty?
- beq.s snd_exit2
- movea.l dqreadptr-DB(a5),a1 ;get read pointer
- move.w (a1)+,d0 ;get message number (D0)
- cmpa.l #dqwriteptr,a1 ;queue end?
- bne.s snd_noresetbuff
- lea dumpqueue-DB(a5),a1 ;reset write pointer
- snd_noresetbuff move.l a1,dqreadptr-DB(a5) ;and write it back.
- subq.w #1,dqentries-DB(a5)
- ; then attempt to search the given message (# in D0)
- move.l _module-DB(a5),d1
- beq.s StartNewDump
- move.l d1,a1
- move.l mmd_expdata(a1),d1
- beq.s StartNewDump
- move.l d1,a1
- move.l 52(a1),d1 ;exp_dump
- beq.s StartNewDump
- move.l d1,a1
- cmp.w (a1),d0
- bge.s StartNewDump
- addq.l #8,a1 ;points to MMDDump ptr table
- add.w d0,d0
- add.w d0,d0 ;number *= 4
- adda.w d0,a1
- movea.l (a1),a1
- ; initialize send variables (msg addr. in A0)
- snd_found move.l (a1)+,sysxleft-DB(a5) ;length
- move.l (a1),sysxptr-DB(a5) ;data pointer
- st sysx-DB(a5)
- rts
- snd_exit2 clr.b sysx-DB(a5) ;finish dump
- rts
-
- _AddMIDIData move.l a6,-(sp)
- lea DB,a6
- bsr.s _AddMIDId
- move.l (sp)+,a6
- rts
-
- _AddMIDId movem.l a1-a3/a5,-(sp)
- tst.b serportalloc-DB(a6)
- beq.s retamd1
- movea.l 4.w,a5
- lea $dff09a,a3
- move.w #$4000,(a3) ;Disable interrupts
- addq.b #1,$126(a5) ;ExecBase->IDNestCnt
- lea buffptr-DB(a6),a2 ;end of buffer (ptr)
- move.w -130(a3),d1 ;-130(a3) = $dff018 (SERDATR)
- btst #13,d1
- beq.s noTBEreq
- move.w #$8001,2(a3) ;request TBE [2(a3) = $dff09c]
- noTBEreq movea.l (a2),a1 ;buffer pointer
- subq.w #1,d0 ;-1 for DBF
- adddataloop move.b (a0)+,d1 ;get byte
- bpl.s norscheck ;this isn't a status byte
- cmp.b #$ef,d1 ;ignore system messages
- bhi.s norscheck
- cmp.b lastcmdbyte-DB(a6),d1 ;same as previous status byte?
- beq.s samesb ;yes, skip
- move.b d1,lastcmdbyte-DB(a6) ;no, don't skip but store.
- norscheck move.b d1,(a1)+ ;push to midi send buffer
- addq.w #1,8(a2)
- samesb cmpa.l a2,a1 ;end of buffer??
- bne.s noresbuffptr ;no.
- lea sendbuffer-DB(a6),a1 ;reset
- noresbuffptr dbf d0,adddataloop
- move.l a1,(a2) ;push back new buffer ptr
- subq.b #1,$126(a5)
- bge.s retamd1
- move.w #$c000,(a3) ;enable interrupts again
- retamd1 movem.l (sp)+,a1-a3/a5
- rts
- ENDC
-
- DATA
- DB: ;Data base pointer
- IFNE MIDI
- sendbuffer ds.b 256
- buffptr dc.l sendbuffer
- readbuffptr dc.l sendbuffer
- bytesinbuff dc.w 0
- sysx dc.b 0
- lastcmdbyte dc.b 0
- sysxptr dc.l 0
- sysxleft dc.l 0
- dumpqueue ds.w 16
- dqwriteptr dc.l dumpqueue
- dqreadptr dc.l dumpqueue
- dqentries dc.w 0
- ENDC
- miscresbase dc.l 0
- timerdiv dc.l 470000
- audiodevopen dc.b 0
- IFNE AUDDEV
- sigbitnum dc.b -1
- ENDC
- IFNE MIDI
- serportalloc dc.b 0
- ENDC
- even
- IFNE MIDI
- preschgdata dc.l 0
- noteondata dc.l 0
- ENDC
- _module dc.l 0
- IFNE MIDI
- bytesinnotebuff dc.w 0
- noteonbuff ds.b (MAX_NUMTRACKS+2)*3
- even
- intrson dc.b 0,0
- prevtbe dc.l 0
- ENDC
- IFNE MIDI
- serinterrupt dc.w 0,0,0,0,0
- dc.l serintname,buffptr,SerIntHandler
- ENDC
- IFNE AUDDEV
- allocport dc.l 0,0 ;succ, pred
- dc.b 4,0 ;NT_MSGPORT
- dc.l 0 ;name
- dc.b 0,0 ;flags = PA_SIGNAL
- dc.l 0 ;task
- reqlist dc.l 0,0,0 ;list head, tail and tailpred
- dc.b 5,0
- allocreq dc.l 0,0
- dc.b 0,127 ;NT_UNKNOWN, use maximum priority (127)
- dc.l 0,allocport ;name, replyport
- dc.w 68 ;length
- dc.l 0 ;io_Device
- dc.l 0 ;io_Unit
- dc.w 0 ;io_Command
- dc.b 0,0 ;io_Flags, io_Error
- dc.w 0 ;ioa_AllocKey
- dc.l challocmask ;ioa_Data
- dc.l 1 ;ioa_Length
- dc.w 0,0,0 ;ioa_Period, Volume, Cycles
- dc.w 0,0,0,0,0,0,0,0,0,0 ;ioa_WriteMsg
- audiodevname dc.b 'audio.device',0
- challocmask dc.b $F
- ENDC
- utilityname dc.b 'utility.library',0
- IFNE MIDI
- serintname dc.b 'OMEDSerialInterrupt',0
- miscresname dc.b 'misc.resource',0
- serdev dc.b 'serial.device',0
- medname dc.b 'OctaMED Pro modplayer',0
- ENDC
- even
- IFNE MIDI
- midiresd dc.b $e0,$00,$40,$b0,$01,$00
-
- midicontrnum ds.b 16
-
- prevmidicpres dc.l 0,0,0,0,0,0,0,0 ; 16 * 2 bytes
-
- ; last MIDI RPN/NRPN (+1, zero = undefined)
- prevmidipn ds.w 16
- ; last MIDI parameter type: RPN = 0, NRPN = 1
- prevmidiptype ds.b 16
-
- prevmidipbend dc.w $2000,$2000,$2000,$2000,$2000,$2000,$2000,$2000
- dc.w $2000,$2000,$2000,$2000,$2000,$2000,$2000,$2000
-
- cmd3xsettings ds.l 15 ;first word = ctrlr type, 2nd word = ctrlr num
- sizeof_mcs EQU 4 ;the size of an entry
- mcs_type EQU 0
- mcs_controller EQU 2
- ENDC
-
- ; TRACK-data structures (see definitions at the end of this file)
- trackdatas ds.b TRACKDATASZ*64
- XDEF trackdataptrs
- ; Build pointer table. This works on Devpac assembler, other assemblers
- ; may need modifications.
- trackdataptrs
- TRKCOUNT SET 0
- REPT 64
- dc.l trackdatas+TRKCOUNT
- TRKCOUNT SET TRKCOUNT+TRACKDATASZ
- ENDR
-
- nextblock dc.b 0 ;\ DON'T SEPARATE
- nxtnoclrln dc.b 0 ;/
- numtracks dc.w 0 ;\ DON'T SEPARATE
- numlines dc.w 0 ;/
- numpages dc.w 0
- nextblockline dc.w 0
- rptline dc.w 0 ;\ DON'T SEPARATE
- rptcounter dc.w 0 ;/
- blkdelay dc.w 0 ;block delay (PT PatternDelay)
- fxplineblk dc.l 0 ;for reading effects
- XDEF maxaudiotrk
- maxaudiotrk dc.w 4 ;max. track number accepting non-MIDI play
-
- ; Fields in struct InstrExt (easier to access this way rather than
- ; searching through the module).
- XDEF flags,rptrptlen
- holdvals ds.b 63
- decays ds.b 63
- finetunes ds.b 63
- flags ds.b 63
- ext_midipsets ds.w 63
- outputdevs ds.b 63
- CNOP 0,4
- rptrptlen ds.l 126
-
- ; ---- user-settable variables
- XDEF _mixbuffsize,_mixfreq,_mix14bit
- _mixbuffsize dc.l 1024
- _mixfreq dc.l 15000
- _mix14bit ds.b 1
- ds.b 3 ;pad
-
- ; ---- non-user-settable variables
- XDEF _chipbuff,_mixbuff,_buffsize,_actualrate_hz
- XDEF _actualrate_fract,_chinfo,_freq_tables
- XDEF _mix_channels,_echobuffer,_echobuffsz,_voltable
- XDEF _echord,_chshift,_sng_struct,UtBase
- XREF _currleft,_currleftfract,_passlength,_passfract
- _chipbuff ds.l 8
- _mixbuff ds.l 2
- _buffsize ds.l 1
- _chinfo ds.l 1
- _frqtblmem ds.l 1
- _freq_tables ds.l 16
- _voltable ds.l 1
- UtBase ds.l 1
- _echobuffer ds.l 1
- _echobuffsz ds.l 1
- _echord ds.l 1
- _sng_struct ds.l 1
- _actualrate_hz dc.w 1
- _actualrate_fract
- ds.w 1
- _mix_channels ds.w 1
- _prevnumch ds.w 1
- _prevadj ds.w 1
- _chshift ds.w 1
- _prevstereo ds.b 1
- _prevfreepan ds.b 1
-
- IFND __G2
- section "datachip",data,chip ;for A68k
- ENDC
- IFD __G2
- section "datachip",data_c ;this is for Devpac 2
- ENDC
- XDEF _modnumm
- _chipzero dc.l 0
- _modnumm dc.w 0 ;number of module to play
- END
-
-