; MIDIOUT9
; automatische detectie MUSIC MODULE / FMI
; zie initmidi routine !
; bij MUSIC MODULE en FMI wordt FMI aangestuurd !

; Muziek routine Midi Tracker
; Written by Hayo Rubingh / adapted by John van Poelgeest
; BASIC MIDI-OUT ROUTINE V1.1
; all rights reserved / (C)1991 

; music in rampage 3  (OUT (&HFE),3)

; aansturing max. 10 verschillende midikanalen tegelijk.

     defb #fe
     defw start,end,exec
     org  #d000

start
; sprongtabel
     jp   midicon	  ; midicontroller data naar midi-out
     jp   convers	  ; sample data ram->audio ram
     jp   startmusic	       ; initialiseer interrupt
     jp   endplay1	  ; herstel interrupt
     jp   instrvol

busy defb 0		  ; 255 als muziek wordt afgespeeld
mint defb 0		  ; 255 bij verzending midi data
		     ; om controller data te versturen
adressen
     defw channel
     defw trans
     defw velocity
     defw drumtoets
     defw midicondata
     defw status
     defw instrbuf
     defw volbuf   
     defw midichan
      

exec 
    
starttrack
     defw #0000
endtrack
     defw #0000
waitrate 
     defb 0
teller
     defb 0
old_hook
     defs 5,201

startmusic
     ld   a,(busy)
     cp   255
     jr   nz,initiaz
     ret

initiaz
     call start1    
     ld   a,255
     ld   (busy),a
     ld   hl,#fd9f
     ld   de,old_hook
     ld   bc,5
     ldir
     call initmodule
     call initmidi	  ; init music module voor midi
     call midicon	  ; stuur midi-controller data 
     call instrvol   

     di
     ld   hl,#8000
     ld   (starttrack),hl
     ld   de,192
     ld   a,(#bff8)
     ld   b,a
     inc  b   
lus100			  ; bereken eindadres music data
     add  hl,de
     djnz lus100
     ld   (endtrack),hl

     ld   a,(#ffe8)	  ; check of computer op 50/60Hz werkt
     bit  1,a		  ; snelheid wordt aangepast.
     jr   z,prul1
     ld   a,(#bf82)
     dec  a
     cp   0
     jr   nz,prul2
     ld   a,1
     jr   prul2
prul1	    
     ld   a,(#bf82)
prul2	    
     ld   (waitrate),a
     dec  a
     ld   (teller),a

     di
     ld   a,201
     ld   (#fd9f),a
     ld   hl,playmusic
     ld   (#fda0),hl
     ld   a,#c3
     ld   (#fd9f),a   
  
     jp   end1
		   ; einde initialisatie
pgfl defs 1,0 

playmusic
     call old_hook
     call start1
     ld   a,(waitrate)
     ld   b,a
     ld   a,(teller)
     inc  a
     ld   (teller),a
     cp   b
     jr   z,playmore   
     jp   end1
playmore
     xor  a
     ld   (teller),a
     cpl
     ld   (mint),a
     ld   hl,(starttrack)
     ld   de,(endtrack)
     rst  #20
     jp   z,endplay
     call play

 

     ld   hl,(starttrack)
     ld   de,musicdata	 
     ld   bc,12
     ldir

     ld   hl,(starttrack)
     ld   de,12
     add  hl,de
     ld   (starttrack),hl
     xor  a
     ld   (mint),a


; check op select toets, schakel midi on/off
     ld   a,(#fbec)
     cp   191
     jp   nz,end1
     ld   a,(midistat)
     xor  255
     ld   (midistat),a	   
     cp   1
     jp   nz,pol
     jp   end1
pol  jp   midioff

initmodule
     ld   hl,regdata	       ; init klanken
     ld   de,#bf00
     ld   b,99
lus91	    
     ld   c,(hl)	  ; register
     inc  hl
     ld   a,(de)	  ; data
     inc  de
     call wrt_module
     djnz lus91

     ld   a,(#bfce)	  ; sustain register
     ld   c,#bd
     call wrt_module

     ld   a,8		  ; module aan
     ld   c,#18
     call wrt_module
     ld   a,8
     ld   c,#19
     call wrt_module
     ret

midicon 	     ; midi controller data
		     ; naar alle 16 midi kanalen
     ld   a,(mint)
     and  255
     jr   nz,midicon

;     di
     push hl
     push af
     push de
     ld   hl,midicondata
     ld   d,0
     ld   b,8
lmidicon
     ld   a,#b0 	  ; controller byte + channel
     or   d
     call midiout
     ld   a,(hl)	  ; controller functie
     call midiout
     inc  hl
     ld   a,(hl)	  ; data
     call midiout
     inc  hl
     djnz lmidicon
     ld   b,8
     inc  d
     ld   a,d
     cp   16
     jr   nz,lmidicon
     pop  de
     pop  af
     pop  hl
;     ei
     ret

instrvol
     di
     ld   b,#c0
     ld   a,b
     ld   hl,instrbuf
llus1 
     call midiout
     ld   a,(hl)
     call midiout
     inc  hl
     inc  b
     ld   a,b
     cp   #d0
     jr   nz,llus1
 
     ld   b,#b0
     ld   a,b
     ld   hl,volbuf
llus2 
     call midiout
     ld   a,7
     call midiout
     ld   a,(hl)
     call midiout
     inc  hl
     inc  b
     ld   a,b
     cp   #c0
     jr   nz,llus2
     ei
     ret
  




play		     ; in hl=starttrack adres
     call playmodule
     ld a,(midistat)
     ret z
     call playmidi
     ret

playmodule
     ld   de,moddata
     ld   b,9
lusmodule
     push bc
     ld   a,9
     sub  b
     ld   b,0		  ; huidig kanaal nummer in bc
     ld   c,a
     push hl
     ld   hl,status
     add  hl,bc
     ld   a,(hl)	  ; status in a
     pop  hl
     bit  0,a
     jr   z,escape1
     ld   a,(hl)
     and  255
     jr   z,escape1
     res  6,a
     call frqsub1	  ; haal frequenties
     ld   a,(de)
     ld   c,a
     ld   a,(r09)
     call wrt_module
     inc  de
     ld   a,(de)
     ld   c,a
     ld   a,(r10)
     call wrt_module
     ld   a,(hl)
     bit  6,a
     jr   nz,keyoff1
     ld   a,(r10)
     set  5,a
     call wrt_module

keyoff1 
     inc  hl
     inc  de
     jr   label01
escape1 
     inc  hl
     inc  de
     inc  de
label01 
     pop  bc
     djnz lusmodule
     call mod_drum
     ret

playmidi
     ld   hl,(starttrack)
     ld   b,9
lusmidi
     push bc
     ld   a,9
     sub  b
     ld   b,0
     ld   c,a
     push hl
     ld   hl,status
     add  hl,bc
     ld   a,(hl)
     pop  hl
     bit  1,a
     jr   z,elusmidi
     ld   a,(hl)
     and  255
     call nz,event	  ; <>0 naar afspeelroutine
elusmidi
     inc  hl
     pop  bc
     djnz lusmidi	  ; bij einde lus staat hl op drumfreq.
     ld   a,(status+9)
     bit  1,a	  
     ret  z 
     ld   a,(hl)	  ; test of drum moet worden afgespeeld
     and  255
     ret  z
     inc  hl		  ; nu op drumvolume
     inc  hl		  ; nu op drum nummer
     call playmididrum
     ret

; Zo zou het moeten werken John !
playmididrum
     ld   a,(hl)
     and  255
     ret  z			; keer terug als drumnr = 0
     push hl   
     push af			; drum nummer (1..16)

     ld   a,(channel+9)
     or   #90
     ld   b,a			; status in  b

     ld   a,(vorigedrum)
     and  a
     jr   z,hoppa

     push af			; vorige drum actie uit
     ld   a,b
     call midiout
     pop  af
     call midiout
     xor  a			; velocity 0 is note off     
     call midiout 



hoppa
     ld   a,b
     call midiout		; status   
     pop  af
     dec  a
     ld   b,0
     ld   c,a
     ld   hl,drumtoets	       ; buffer met drum toets nummers1..16
     add  hl,bc
     ld   a,(hl)
     ld   (vorigedrum),a
     call midiout
     pop  hl   
     dec  hl   
     ld   a,(hl)   
     srl  a   
     call midiout
     ret

vorigedrum
	defb	0

event			  ; in hl=starttrack adres
     push hl		  ; bc=kanaalnummer 0..8
     bit  6,a		  ; a=nootnummer fac formaat
     call nz,keyoff
     call z,keyon
     pop  hl
     ret

keyon
     push af		  ; nootnummer fac formaat op stack
     ld   hl,keybuf	  ; keybuf vorige interrupt
     add  hl,bc
     ld   a,(hl)	  ; vorige nootnummer fac formaat
     bit  6,a
     call z,keyoff2	  ; deze noot moet nog worden uitgezet
vorigenul
     ld   hl,channel	       ; 
     add  hl,bc
     ld   a,(hl)
     or   %10010000
     call midiout
     ld   hl,trans
     add  hl,bc
     ld   d,(hl)
     pop  af		  ; fac formaat noot van stack
     ld   hl,keybuf	  ; plaats in keybuf
     add  hl,bc
     ld   (hl),a
     and  %00111111
     add  a,d
     call midiout
     ld   hl,velocity
     add  hl,bc
     ld   a,(hl)
     call midiout
     ret

keyoff
     ld   hl,keybuf	  ; plaats in keybuf
     add  hl,bc
     ld   (hl),a
     and  %00111111	  ; maak b7,6 0
keyoff2
     push af
     ld   hl,channel	       ; haal midi kanaal nummer
     add  hl,bc
     ld   a,(hl)
     or   %10010000	  ; +$90
     call midiout

     ld   hl,trans
     add  hl,bc
     pop  af
     add  a,(hl)
     call midiout
     xor  a		  ; velocity 0 = aanslagsnelheid 0
     call midiout
     or   1		  ; Z flag 0
     ret
     

wrt_module		  ; schrijf music module
     push af
     ld   a,c
     out  (#c0),a
     ex   (sp),hl
     ex   (sp),hl
     pop  af
     out  (#c1),a
     ret

mod_drum
     ld   a,(status+9)
     bit  0,a
     jr   z,nodrum
     ld   a,(hl)
     cp   #00
     jr   z,nodrum
     call drumfreq
     inc  hl
     ld   a,(hl)
     call drumvol1
     ld   a,1
     ld   c,7
     call wrt_module
     inc  hl
     ld   a,(hl)
     call drumsnd1
     call play_drum1
     inc  hl
     ret
nodrum
     inc  hl
     inc  hl
     inc  hl
     ret

play_drum1
     ld   a,#a0
     ld   c,7
     call wrt_module
     ret

drumfreq
     push hl
     ld   hl,drumdata
     dec  a
     add  a,a
     ld   c,a
     ld   b,0
     add  hl,bc
     ld   a,(hl)
     ld   c,17
     call wrt_module
     inc  hl
     ld   a,(hl)
     ld   c,16
     call wrt_module
     pop  hl
     ret

frqsub1 
     push hl
     ld   hl,frqdat1
     dec  a
     add  a,a
     ld   c,a
     ld   b,0
     add  hl,bc
     ld   a,(hl)
     ld   (r09),a
     inc  hl
     ld   a,(hl)
     ld   (r10),a
     pop  hl
     ret

drumvol1
     push hl
     ld   c,18
     call wrt_module
     pop  hl
     ret


drumsnd1
     push hl
     dec  a
     add  a,a
     add  a,a
     ld   hl,sounddata
     ld   c,a
     ld   b,0
     add  hl,bc
     ld   a,(hl)
     ld   c,10
     call wrt_module
     inc  hl
     ld   a,(hl)
     ld   c,9
     call wrt_module
     inc  hl
     ld   a,(hl)
     ld   c,12
     call wrt_module
     inc  hl
     ld   a,(hl)
     ld   c,11
     call wrt_module
     pop  hl
     ret

regdata
     defb #20,#23,#40,#43,#60,#63,#80,#83,#a0,#b0,#c0
     defb #21,#24,#41,#44,#61,#64,#81,#84,#a1,#b1,#c1
     defb #22,#25,#42,#45,#62,#65,#82,#85,#a2,#b2,#c2
     defb #28,#2b,#48,#4b,#68,#6b,#88,#8b,#a3,#b3,#c3
     defb #29,#2c,#49,#4c,#69,#6c,#89,#8c,#a4,#b4,#c4
     defb #2a,#2d,#4a,#4d,#6a,#6d,#8a,#8d,#a5,#b5,#c5
     defb #30,#33,#50,#53,#70,#73,#90,#93,#a6,#b6,#c6
     defb #31,#34,#51,#54,#71,#74,#91,#94,#a7,#b7,#c7
     defb #32,#35,#52,#55,#72,#75,#92,#95,#a8,#b8,#c8

frqdat1 
     defb #59,#09,#6d,#09,#83,#09,#9a,#09,#b2,#09,#cc,#09,#e8,#09
     defb #05,#0a,#23,#0a,#44,#0a,#67,#0a,#8b,#0a
     defb #59,#0d,#6d,#0d,#83,#0d,#9a,#0d,#b2,#0d,#cc,#0d,#e8,#0d
     defb #05,#0e,#23,#0e,#44,#0e,#67,#0e,#8b,#0e
     defb #59,#11,#6d,#11,#83,#11,#9a,#11,#b2,#11,#cc,#11,#e8,#11
     defb #05,#12,#23,#12,#44,#12,#67,#12,#8b,#12
     defb #59,#15,#6d,#15,#83,#15,#9a,#15,#b2,#15,#cc,#15,#e8,#15
     defb #05,#16,#23,#16,#44,#16,#67,#16,#8b,#16
     defb #59,#19,#6d,#19,#83,#19,#9a,#19,#b2,#19,#cc,#19,#e8,#19
     defb #05,#1a,#23,#1a,#44,#1a,#67,#1a,#8b,#1a
     defb #59,#1d,#6d,#1d,#83,#1d,#9a,#1d

frqdat2 
     defb #ad,#b7,#c2,#cd,#d9,#e6,#f4,#03,#12,#22,#34,#46
     defb #ad,#b7,#c2,#cd,#d9,#e6,#f4,#03,#12,#22,#34,#46
     defb #ad,#b7,#c2,#cd,#d9,#e6,#f4,#03,#12,#22,#34,#46
     defb #ad,#b7,#c2,#cd,#d9,#e6,#f4,#03,#12,#22,#34,#46
     defb #ad,#b7,#c2,#cd,#d9,#e6,#f4,#03,#12,#22,#34,#46
     defb #ad,#b7,#c2,#cd,#d9,#e6

moddata 
     defb #a0,#b0,#a1,#b1,#a2,#b2,#a3,#b3,#a4,#b4,#a5,#b5,#a6,#b6
     defb #a7,#b7,#a8,#b8

drumdata
     defb #05,#22,#05,#6a,#05,#ba,#06,#12,#06,#73,#06,#d3
     defb #07,#3b,#07,#ab,#08,#1b,#08,#9c,#09,#24,#09,#ac
     defb #0a,#3d,#0a,#d5,#0b,#7d,#0c,#2d,#0c,#e6,#0d,#a6
     defb #0e,#7f,#0f,#57,#10,#3f,#11,#38,#12,#40,#13,#51
     defb #14,#7a,#15,#aa,#16,#fb,#18,#5b,#19,#c4,#1b,#4d
     defb #1c,#fe,#1e,#b6,#20,#77,#22,#70,#24,#81,#26,#aa
     defb #28,#fc,#2b,#5d,#2d,#f6,#30,#af,#33,#89,#36,#a2
     defb #39,#f4,#3d,#66,#40,#f7,#44,#e1,#49,#0b,#4d,#4d
     defb #51,#f0,#56,#b2,#5b,#ec,#61,#5f,#67,#1a,#6d,#45
     defb #73,#e8,#7a,#cb,#81,#f0,#89,#c4,#92,#18,#9a,#a4

sounddata
     defb #00,#00,#03,#ff ; drum 1
     defb #04,#00,#07,#ff ; drum 2
     defb #08,#00,#0b,#ff ; drum 3
     defb #0c,#00,#0f,#ff ; drum 4
     defb #10,#00,#13,#ff ; drum 5
     defb #14,#00,#17,#ff ; drum 6
     defb #18,#00,#1b,#ff ; drum 7
     defb #1c,#00,#1f,#ff ; drum 8

     defb #00,#00,#07,#ff ; drum 1+2
     defb #08,#00,#0f,#ff ; drum 3+4
     defb #10,#00,#17,#ff ; drum 5+6
     defb #18,#00,#1f,#ff ; drum 7+8

     defb #00,#00,#0f,#ff ; drum 1+2+3+4
     defb #10,#00,#1f,#ff ; drum 5+6+7+8

     defb #00,#00,#1f,#ff ; drum 1+2+3+4+5+6+7+8
     defs 4,0

; midi data
channel
     defb 0,1,2,3,4,5,6,7,7,9
trans
     defb 23,23,23,23,23,23,23,23,23,23
velocity
     defb 64,64,64,64,64,64,64,64,64,64
drumtoets	     
     defb 36,38,42,43,46,61,63,52
     defb 68,69,70,71,72,73,74,75
keybuf
     defs 9,0
midicondata
     defb #1,0,#2,0,#a,0,#5,0,#40,0,#41,0,#42,0,#43,0 ; channel 0
     defb #1,0,#2,0,#a,0,#5,0,#40,0,#41,0,#42,0,#43,0 ; channel 1
     defb #1,0,#2,0,#a,0,#5,0,#40,0,#41,0,#42,0,#43,0 ; channel 2
     defb #1,0,#2,0,#a,0,#5,0,#40,0,#41,0,#42,0,#43,0 ; channel 3
     defb #1,0,#2,0,#a,0,#5,0,#40,0,#41,0,#42,0,#43,0 ; channel 4
     defb #1,0,#2,0,#a,0,#5,0,#40,0,#41,0,#42,0,#43,0 ; channel 5
     defb #1,0,#2,0,#a,0,#5,0,#40,0,#41,0,#42,0,#43,0 ; channel 6
     defb #1,0,#2,0,#a,0,#5,0,#40,0,#41,0,#42,0,#43,0 ; channel 7
     defb #1,0,#2,0,#a,0,#5,0,#40,0,#41,0,#42,0,#43,0 ; channel 8
     defb #1,0,#2,0,#a,0,#5,0,#40,0,#41,0,#42,0,#43,0 ; channel 9
     defb #1,0,#2,0,#a,0,#5,0,#40,0,#41,0,#42,0,#43,0 ; channel 10
     defb #1,0,#2,0,#a,0,#5,0,#40,0,#41,0,#42,0,#43,0 ; channel 11
     defb #1,0,#2,0,#a,0,#5,0,#40,0,#41,0,#42,0,#43,0 ; channel 12
     defb #1,0,#2,0,#a,0,#5,0,#40,0,#41,0,#42,0,#43,0 ; channel 13
     defb #1,0,#2,0,#a,0,#5,0,#40,0,#41,0,#42,0,#43,0 ; channel 14
     defb #1,0,#2,0,#a,0,#5,0,#40,0,#41,0,#42,0,#43,0 ; channel 15

; de hex waarden zijn de controller nummers gevold door data byte

; #1  modulatiewiel	  [0..127]
; #2  breath controller       [0..127]
; #a  panpot		  [0..???]
; #5  portamento time	       [0..127]
;
; #40 sustain-pedaal	       [0=uit]
; #41 portamento	  [0=uit]
; #42 sostenuto 	  [0=uit]
; #43 soft		  [0=uit]

status			  ; bevat informatie per fm kanaal + dr
     defb 3,3,3,3,3,3,3,3,3,3
; betekenis afzonderlijke bits
; 0 = data naar music module [1]
; 1 = data naar midi out [1]
; 2..7 = nog geen functie

instrbuf
     defb 94,3,3,3,3,33,33,33
     defb 33,33,33,33,33,33,33,33
  


volbuf	     
     defb 64,64,64,64,64,64,64,64
     defb 64,64,64,64,64,64,64,64    
midichan
     defb 0

r09  defb 0
r10  defb 0
track
     defb 0
curchan 
     defb 0
start_data
     defw #8000
sampdeel
     defb 1
convers
     ld   a,(sampdeel)
     xor  1
     ld   (sampdeel),a
     cp   0
     call z,kn1
     ld   a,(sampdeel)
     cp   1
     call z,kn2
     


     di
     ld   a,4
     out  (#c0),a
     ld   a,#60
     out  (#c1),a


     ld   bc,#4000
     ld   hl,#8000
lus30	    ld	 a,15
     out  (#c0),a
     ld   a,(hl)
     out  (#c1),a
     ld   a,4
     out  (#c0),a
     ld   a,#80
     out  (#c1),a
     inc  hl
     dec  bc
     ld   a,b
     or   c
     jr   z,gabel1
gabel2
     in   a,(#c0)
     bit  7,a
     jr   z,gabel2
     bit  4,a
     jr   z,lus30
gabel1
     nop
     ld   a,4
     out  (#c0),a
     ld   a,#78
     out  (#c1),a
     ld   a,#80
     out  (#c1),a
     ld   a,7
     out  (#c0),a
     ld   a,1
     out  (#c1),a
     ei
     ret


endplay1
    call start1


endplay
     di
     ld   hl,old_hook
     ld   de,#fd9f
     ld   bc,5
     ldir
     xor  a
     ld   (busy),a
     ld   (mint),a
geluid_uit
     ld   hl,moddata
     ld   b,18
lusuit	    
     ld   c,(hl)
     xor  a
     call wrt_module
     inc  hl
     djnz lusuit

; nieuwe uit routine !!!
midioff
	ld	a,(channel+9)
	or	#90
	call	midiout
	ld	a,(vorigedrum)
	dec	a
	ld	c,a
	ld	b,0
	ld	hl,drumtoets
	add	hl,bc
	ld	a,(hl)
	call	midiout
	xor	a
	call	midiout

	ld	hl,keybuf
	ld	bc,0
rlusuit  ld	 a,(hl)
	push	hl
	call	keyoff2
	pop	hl
	inc	hl
	inc	bc
	ld	a,c
	cp	9
	jr	nz,rlusuit
     jp   end1


kn1  
     ld   b,9
     ld   hl,kn1dat
knn1 
     ld   a,(hl)
     out  (#c0),a
     inc  hl
     ld   a,(hl)
     out  (#c1),a
     inc  hl
     djnz knn1
     ret
kn2  
     ld   b,9
     ld   hl,kn2dat
     jr   knn1

kn1dat	    
     defb 4,#78,7,1,8,0,9,0,10,0,11,255,12,#f,16,#f0,7,#60
kn2dat	    
     defb 4,#78,7,1,8,0,9,0,10,#10,11,255,12,#1f,16,#f0,7,#60

start1 
     di
     ld c,254
     in a,(c)
     ld (pgfl),a
     ld a,3
     out (#fe),a
     ret

end1
     ld a,(pgfl)
     out (#fe),a
     ei
     ret

musicdata
     defs 12,0

midiout
	defb	#c3
madres1 defw	0

midi_init
	defb	#c3
madres2 defw	0

initmidi
	or	255
	ld	(testmod),a
	in	a,(2)
	cp	255
	jr	nz,fmi		; hoera ! fmi aanwezig
	in	a,(#c0)
	cp	255
	jp	z,geenmod	; geen module en geen fmi
	ld	hl,mod_out
	ld	(madres1),hl
	ld	hl,mod_init
	ld	(madres2),hl
	call	midi_init
	ret
fmi	ld	hl,fmi_out
	ld	(madres1),hl
	ld	hl,fmi_init
	ld	(madres2),hl
	call	midi_init
	ret
geenmod xor	a
	ld	(testmod),a
	ret

mod_out
	push	af
mod_out2
	in	a,(4)
	and	2
	jp	z,mod_out2
	pop	af
	out	(1),a
	ret
mod_init
	ld	a,3
	out	(0),a
	ld	a,21
	out	(0),a
	ret
fmi_out
	push	af
fmi_out2
	in	a,(3)
	and	1
	jp	z,fmi_out2
	pop	af
	out	(2),a
	ret
fmi_init
	xor	a
	out	(3),a
	out	(3),a
	out	(3),a
	ld	a,#40
	out	(3),a
	ld	a,#4e
	out	(3),a
	ld	a,#15
	out	(3),a
	ret

testmod
; 0 als er geen music module en/of fmi aanwezig is
; anders 255
; kun je dus op testen na aanroep !

	defb	255
midistat
	defb	0



end
