*W ;Downloaded from http://www.cx5m.net ; MSLAVE.GEN VER 1.4 ;This program makes the CX5M a midi ;slave. DEFB 0FEH ;BINARY FILE DEFW CODSTT DEFW ENDCOD DEFW CODSTT ;This program allows eight instruments ;with unique midi channels to be played ;remotely by a synth or sequencer. ;While waiting for a midi byte it ;checks for the stop key. If the ;stop key is pressed, the program ;terminates and does a hard reboot. ;In coding this program I purposely ;chose run-speed over code-efficiency, ;which means instead of making ;loops I repeated code to make it ;run faster. UVL1 EQU 08100H UVL2 EQU UVL1+3111 BOTSTK EQU 0DB00H ; MIDB EQU BOTSTK-800H RXBUF EQU MIDB-100H TXBUF EQU RXBUF-100H IDB7BF EQU TXBUF-80H IDB6BF EQU IDB7BF-80H IDB5BF EQU IDB6BF-80H IDB4BF EQU IDB5BF-80H IDB3BF EQU IDB4BF-80H IDB2BF EQU IDB3BF-80H IDB1BF EQU IDB2BF-80H IDB0BF EQU IDB1BF-80H MSXFCB EQU IDB0BF-25H CHARSET EQU MSXFCB-400H SCRARR EQU CHARSET-300H MIDSTT EQU 3FF6H MIDDAT EQU 3FF5H IO_PPA EQU 0A8H ;PRIMARY SLOT REG IO_KBD EQU 0AAH ;KBD ROW SEL IN_KBD EQU 0A9H ;KBD READ MM_PPA EQU 0FFFFH ;secondary slot reg M_ICKA EQU MIDB+32H; AST01 EQU MIDB+3CH; ; for use when loading with BASIC ; as a binary file. So BASIC will ;know where to load it and run it. CODSTT ORG 0AE00H ;INITIAL SETUP PROCEDURE JP MSINIT JP RWFILE JP MSLAVE JP SETMID JP SYSXTX JP SHOHEX ;################################### ICALL DI CALL 00ABH RET ;################################### ECALL DI CALL 00B7H RET ;################################### RCALL EI CALL 0093H RET ;################################### PCALL EI LD A,0 CALL 0099H RET ;################################### SCALL EI CALL 009CH RET ;################################### MCALL EI CALL 00A5H RET ;################################### FCALL EI CALL 00B1H RET ;################################### KCALL EI CALL 0096H RET ;################################### CHKSTP ;check for stop key, return with ;zero flag set if pressed IN A,(IN_KBD) BIT 4,A RET Z AND 03H LD HL,LASKEY CP (HL) JP Z,NOCHG LD (HL),A ; IF F5 KEY ON THEN TOGGLE ; SCREEN UPDATE BIT 1,A JP NZ,CHKST0 PUSH AF LD A,(SCRUPD) CP 0C3H JP Z,CHKST1 LD A,0C3H CHKST2: LD (SCRUPD),A CALL SHOWUP POP AF JP CHKST0 CHKST1: LD A,0C9H JP CHKST2 CHKST0 BIT 0,A RET NZ LD A,(MIDIFG) CPL LD (MIDIFG),A CALL SETMID CALL SHOWMT NOCHG OR 0FFH RET ;%%%%%%%% SHOHEX: ; display space, then hex of value ; in A PUSH AF LD A,20H CALL OUTCHR POP AF PUSH AF SRL A SRL A SRL A SRL A ADD A,30H CP 3AH JP C,SHOHX1 ADD A,7 SHOHX1: CALL OUTCHR POP AF AND 0FH ADD A,30H CP 3AH JP C,SHOHX2 ADD A,7 SHOHX2: CALL OUTCHR LD A,20H CALL OUTCHR RET ;*********************************** GETPAK: ;given pointer in DE and ;first byte in A, returns 0 flag ; if midi in found stop key, ; or no carry if invalid packet. ; else carry = 1 ; puts count in C, checksum in B ; get count bytes LD C,A PUSH BC PUSH DE CALL MIDIIN POP DE POP BC RET Z ;combine them SLA A RR C RR A LD C,A LD B,0 GETPK0: PUSH DE PUSH BC CALL MIDIIN POP BC POP DE RET Z LD L,A ADD A,B LD B,A PUSH DE PUSH BC PUSH HL CALL MIDIIN POP HL POP BC POP DE RET Z PUSH AF ADD A,B LD B,A POP AF SLA A SLA A SLA A SLA A OR L ; store at pointer and increment LD (DE),A INC DE ; decrement count DEC C DEC C JP NZ,GETPK0 ; get checksum PUSH DE PUSH BC CALL MIDIIN POP BC POP DE RET Z ADD A,B AND 07FH OR A JP Z,PAKOK ;return not zero and no carry LD A,01H INC A RET ;return not zero and carry PAKOK: LD A,0FFH ADD A,2 RET ;******************************* ; get configuration data dump GETFIG: CALL MIDIIN JP Z,NOMORE LD DE,8000H JP GETVB0 ;*********************************** GETVBK: ; receive sys ex dump of voice bank CALL MIDIIN JP Z,NOMORE ; if bank number too high then ; return CP 2 JP NC,F7ERR; LD (BANKNM),A ; pointer for data in DE LD DE,UVL1 OR A JP Z,GETVB0 LD DE,UVL2 GETVB0: PUSH DE CALL MIDIIN POP DE JP Z,NOMORE CP 0F7H JP Z,SSXDON CALL GETPAK ; returns with de to next place ; if z then stop key pressed ; if carry then error JP Z,NOMORE JP NC,SUMERR JP GETVB0 SSXDON: LD A,(BANKNM) LD HL,UVL1 LD BC,8 LD DE,FCB1+6 OR A JP Z,SSXMV LD HL,UVL2 LD DE,FCB2+6 DEC A JP NZ,SSXEND SSXMV: LDIR SSXEND: CALL MKSCRN LD HL,REDLIT CALL OUTSTR JP GETSTAT ;################################### CVRTVC ; Given voice number 1-96 in C ; converts it to 64-112 and ; defines one of two voice banks. ; Returns converted value in A ; If voice >= 49 LD A,C CP 49 JP C,CVERT0 ;then PUSH BC ; define uvl 2 CALL DFUVL2 POP BC ; voice = voice + 15 LD A,C ADD A,15 RET CVERT0 ;else PUSH BC ; define uvl 1 CALL DFUVL1 POP BC ; voice = voice + 63 LD A,C ADD A,63 RET ;################################### INIUVL ; copies system voices to uvl ; do x= 1 to 48 LD B,0 LD DE,IDB0BF LD A,0 CALL SCALL LD E,48 INIU0 PUSH DE LD A,E DEC A LD C,A ;VOICE # LD B,0 ;IDB0 USED PUSH BC LD A,15H ;GETVOICE CALL SCALL POP BC LD A,C ADD A,64 ;VOICE = VOICE + 64 LD C,A LD A,16H ;PUT VOICE CALL SCALL POP DE DEC E JP NZ,INIU0 RET ;################################### SETVOC ; Given IDB number in B, voice in C, ; velocity in A, ; and pointer to IDB in DE ; initialize queue, and load voice. ; Define the IDB PUSH AF PUSH BC PUSH DE LD A,0 CALL SCALL POP DE POP BC ; Assign IDB to queue PUSH BC LD A,B OR 80H LD D,A LD A,0AH LD E,0 CALL SCALL POP BC ; Get and load voice PUSH BC CALL CVRTVC ;CONVERT VOICE POP BC LD C,A PUSH BC LD A,19H CALL SCALL POP BC ; Set volume POP AF LD C,A LD A,13H CALL SCALL RET ;################################## DFUVL1 ;defines uvl to uvl1 LD A,03H LD DE,UVL1 CALL SCALL RET ;################################## DFUVL2 ;defines uvl to uvl2 LD A,03H LD DE,UVL2 CALL SCALL RET ;################################## SUBINI: ;Set memory page,mbios mode and ;midb location DI ;save original setting of primary ;slot selector IN A,(IO_PPA) LD (PRISLT),A ;set to slot 3 for low page OR 03H OUT (IO_PPA),A ;save original setting of secondary ;slot selector LD A,(MM_PPA) CPL LD (SECSLT),A ;set to slot 3 for low page OR 03H LD (MM_PPA),A ;Set mode 2.0 init LD DE,MIDB CALL ICALL ; disable clock B - not used LD C,01H LD A,0DH CALL SCALL RET ;********************************** MSLVXT: ; exit mslave. call e-call,set ;page = 0 and return. CALL ECALL LD A,(SECSLT) LD (MM_PPA),A LD A,(PRISLT) OUT (IO_PPA),A RET ;********************************** MSINIT CALL SUBINI ;Define user voice buffer CALL DFUVL1 ;Initialize to system voices CALL INIUVL CALL DFUVL2 CALL INIUVL CALL MSLVXT RET ;********************************** RWFILE: ;given ptr to FCB in HL, and ;0 for read, 01h for write file ; If filename starts with space ; then just ; initialize with mbios voices PUSH HL ; copy file name to oldnam to save LD DE,6 ADD HL,DE LD DE,OLDNAM LD BC,8 LDIR CALL SUBINI LD HL,LOADMS CALL OUTSTR POP HL PUSH HL LD DE,17 ADD HL,DE LD E,(HL) INC HL LD D,(HL) LD A,03H ;DEF UVL CALL SCALL POP HL PUSH HL LD DE,6 ADD HL,DE LD A,(HL) CP 20H POP DE JP NZ,RWFIL1 CALL INIUVL JP RWFILX RWFIL1: PUSH DE ;save fcb ptr LD A,20H CALL SCALL POP HL JP C,RWFILQ ; restore name PUSH HL LD DE,6 ADD HL,DE EX DE,HL LD HL,OLDNAM LD BC,8 LDIR POP HL INC HL ;get device code LD A,(HL) DEC HL OR A ; if code = 0 for cassette ; then repeat JP NZ,RWFILX PUSH HL CALL CPNAME POP HL ; if ok then done JP NZ,RWFILQ ;else ignore difference RWFILX: CALL MSLVXT RET RWFILQ: CALL MSLVXT LD C,"?" CALL FILERR RET ;@@@@@@@@@@@@@@@@@@@@@@@@@@@ CPNAME: ;given FCB ptr in HL, compare ; name in FCb with name in UVL ; return 0 if the same, else NZ PUSH HL ;get uvl ptr LD DE,17 ADD HL,DE LD E,(HL) INC HL LD D,(HL) POP HL PUSH DE LD DE,6 ADD HL,DE POP DE LD C,8 CPNAM0: LD A,(DE) CP (HL) RET NZ INC HL INC DE DEC C JP NZ,CPNAM0 RET ;&&&&&&&&&&&&&&&&&&&&&&&&&&&& SHOUT: ; shows midi data being sent ; and sends it PUSH AF CALL SHOHEX POP AF CALL MIDOUT RET ;%%%%%%%%%%%%%%%%%%%%%%%%%%%% SYSXTX: ; given filenumber 0-2 in C ; puts pointer in DE ; and block size in HL ; sends block out via midi sys-ex ; transmit PUSH BC CALL SUBINI ; set to no midi thru ; and check transmit LD HL,MIDI05 LD (MIDIXX+1),HL LD HL,MIDI08 LD (MIDI04+1),HL ; init midi for transmit only LD A,05H LD BC,TXBUF LD DE,0 CALL SCALL ; initialize buffers LD HL,0 LD (BUFIFL),HL LD (BUFOFL),HL ; set midi vector DI LD HL,MIDINT LD (0F975H),HL EI ; send header LD BC,0101H CALL SETCRS LD A,0F0H CALL SHOUT LD A,43H CALL SHOUT LD A,75H CALL SHOUT LD A,(SYSCHN) CALL SHOUT XOR A CALL SHOUT POP BC LD B,0; next byte to send LD DE,UVL1 LD HL,3104 LD A,C OR A JP Z,SYSXT0 LD DE,UVL2 LD A,C DEC A JP Z,SYSXT0 LD DE,8000H LD HL,CLS-8000H; end of data LD BC,0400H SYSXT0: PUSH HL PUSH DE PUSH BC LD A,B CALL SHOUT POP BC LD A,C CALL SHOUT POP DE POP HL ; now send packets ; do while block count (hl) > 0 DO1: LD A,H OR L JP Z,ENDO1 ; if hl > 64 LD A,H OR A JP NZ,THEN LD A,L CP 65 JP C,ELSE ; then count = 64 THEN: LD B,64 JP ENDIF ; else count = hl ELSE: LD B,L ENDIF: LD A,B SLA A; packetCOUNT * 2 PUSH BC PUSH DE PUSH HL CALL SNDCNT POP HL POP DE POP BC ; init checksum LD C,0; ; do while packetcount > 0 DO2: LD A,B OR A JP Z,ENDO2 ; get low half of byte LD A,(DE) AND 0FH PUSH AF ; add to checksum ADD A,C LD C,A POP AF PUSH BC PUSH DE PUSH HL ; send low half CALL SHOUT POP HL POP DE POP BC LD A,(DE) ; get high half SRL A SRL A SRL A SRL A AND 0FH PUSH AF ; add to checksum ADD A,C LD C,A POP AF PUSH BC PUSH DE PUSH HL ; send high half CALL SHOUT POP HL POP DE POP BC ; dec block count, packet count ; inc pointer DEC HL DEC B INC DE JP DO2 ; end ENDO2: ; send checksum LD A,C CPL INC A AND 7FH PUSH BC PUSH DE PUSH HL CALL SHOUT POP HL POP DE POP BC ; end JP DO1 ENDO1: LD A,0F7H CALL SHOUT WAIT: LD HL,(BUFOFL) LD A,H CP L JP NZ,WAIT CALL MSLVXT CALL MKSCRN RET ;%%%%%%%%%%%%%%%%%%%%%%%%%%%% SNDCNT: ; given count in A ; sends it as two bytes 7 bits each LD C,A XOR A BIT 7,C JP Z,SNDCN2 LD A,01H SNDCN2: PUSH BC CALL SHOUT POP BC LD A,C AND 07FH CALL SHOUT RET ;&&&&&&&&&&&&&&&&&&&&&&&&&&&& INITMD: ;Init scan for STOP key IN A,(IO_KBD) AND 0F0H OR 07H OUT (IO_KBD),A ; setup hook for clock-A handler ; for portamento and pitchbend and ; detune LD HL,IRQA LD (M_ICKA),HL ;set vector for midithru or not CALL SETMID ;set vector for interrupt driven ;midi transmit CALL SETTX ; setup midi interrupt vector ; and init circular buffers LD HL,0 LD (BUFIFL),HL LD (BUFOFL),HL ;Init FIFO'S LD BC,TXBUF PUSH BC CALL ISYKON POP BC JP NZ, FIF1 LD BC,0 FIF1: LD A,05H LD DE,RXBUF CALL SCALL DI LD HL,MIDINT LD (0F975H),HL EI RET ;################################# SETMID: ; depending upon midifg, set ; midi vector ; default is no midi thru LD HL,MIDI05 LD A,(MIDIFG) OR A JP Z,SETVEC ; set to midi thru LD HL,MIDI02 SETVEC: LD (MIDIXX+1),HL RET ;############## SETTX: ; default is no transmit LD HL,MIDI07 PUSH HL CALL ISYKON POP HL JP Z,SETTX1 ; set for midi transmit check LD HL,MIDI08 SETTX1: LD (MIDI04+1),HL RET ;*********************************** OTHRIN: ;other initialization ;Init voices from VOICES table ; LD DE,IDB0BF LD B,0 LD A,(VOICES) LD C,A LD A,(VELTBL) CALL SETVOC LD HL,(DETUNE) LD (IDB0BF+3),HL LD DE,IDB1BF LD B,1 LD A,(VOICES+1) LD C,A LD A,(VELTBL+1) CALL SETVOC LD HL,(DETUNE+2) LD (IDB1BF+3),HL LD DE,IDB2BF LD B,2 LD A,(VOICES+2) LD C,A LD A,(VELTBL+2) CALL SETVOC LD HL,(DETUNE+4) LD (IDB2BF+3),HL LD DE,IDB3BF LD B,3 LD A,(VOICES+3) LD C,A LD A,(VELTBL+3) CALL SETVOC LD HL,(DETUNE+6) LD (IDB3BF+3),HL LD DE,IDB4BF LD B,4 LD A,(VOICES+4) LD C,A LD A,(VELTBL+4) CALL SETVOC LD HL,(DETUNE+8) LD (IDB4BF+3),HL LD DE,IDB5BF LD B,5 LD A,(VOICES+5) LD C,A LD A,(VELTBL+5) CALL SETVOC LD HL,(DETUNE+10) LD (IDB5BF+3),HL LD DE,IDB6BF LD B,6 LD A,(VOICES+6) LD C,A LD A,(VELTBL+6) CALL SETVOC LD HL,(DETUNE+12) LD (IDB6BF+3),HL LD DE,IDB7BF LD B,7 LD A,(VOICES+7) LD C,A LD A,(VELTBL+7) CALL SETVOC LD HL,(DETUNE+14) LD (IDB7BF+3),HL ; ;Assign fm channels to IDB'S LD A,(ALLOC) LD B,A LD A,(ALLOC+1) LD C,A LD A,(ALLOC+2) LD D,A LD A,(ALLOC+3) LD E,A LD A,09H CALL SCALL ; set up MIDIUS table. ; for x = 0 to 7 ; if poly(x) = 0 ; then midius (x) = 0ffh ; play routines use midius LD BC,8 OTHR01: LD HL,POLY ADD HL,BC DEC HL LD A,(HL) OR A LD A,0FFH JP Z,OTHR02 LD HL,MIDITB ADD HL,BC DEC HL LD A,(HL) OTHR02: LD HL,MIDIUS ADD HL,BC DEC HL LD (HL),A DEC C JP NZ,OTHR01 ; init YK keyboard LD HL,MKIDBS LD B,8 INITY0: LD A,(HL) OR A JP NZ,INITYK INC HL DEC B JP NZ,INITY0 JP OTHRX INITYK: LD HL,MKIN LD (AST01),HL LD HL,MIDII0 LD (MIDIIN+1),HL LD A,0 LD BC,0 LD D,0A0H; default vel. CALL KCALL OTHRX: RET ;END OF INIT ;############ MIDOUT: ;send char in A to txbuf LD C,A LD HL,(BUFOFL) LD A,L INC A CP H JP Z,MIDOUT LD HL,TXBUF LD E,A LD D,0 ADD HL,DE LD (HL),C LD (BUFOFL),A LD A,(0F9A5H) SET 1,A LD (0F9A5H),A LD (MIDSTT),A RET ;################################### ;MIDIIN ; Poll for midi byte. returning ; it in A and D ; If stop key pressed,issue all ; note off and abort program. MIDIIN: JP MIDII1 MIDII0: LD A,01H CALL KCALL MIDII1: ;If stop key pressed CALL CHKSTP ;then RET Z else POLL: LD HL,(BUFIFL) LD A,L SUB H JP Z,MIDIIN LD A,H INC A LD (BUFIEM),A LD E,A LD D,0 LD HL,RXBUF ADD HL,DE LD A,(HL) CP 0FCH RET NZ LD A,0 CALL RCALL JP MIDIIN ;########## CVOPM: ;given OPM FORMAT ;event in DE, fills STAT ;and MINOTE for midi equivalent LD B,80H LD A,D BIT 7,A JP Z,CVOP1 LD B,90H CVOP1: LD A,B LD (STAT),A LD HL,0691H LD B,0 LD C,D RES 7,C ADD HL,BC LD A,(HL) LD (MINOTE),A RET ;################################### PLAYIT: ; DE contains note and veloc ; convert to opm event format LD A,(MIDICH) OR 90H LD C,A CALL 0C0H LD A,C AND 0FH LD C,A LD HL,0 ; LD A,(MIDIUS) CP C JP NZ,PLAY01 PUSH BC LD B,0 CALL PUTINQ POP BC SET 0,L PLAY01: LD A,(MIDIUS+1) CP C JP NZ,PLAY02 PUSH BC LD B,1 CALL PUTINQ POP BC SET 1,L PLAY02: LD A,(MIDIUS+2) CP C JP NZ,PLAY03 PUSH BC LD B,2 CALL PUTINQ POP BC SET 2,L PLAY03: LD A,(MIDIUS+3) CP C JP NZ,PLAY04 PUSH BC LD B,3 CALL PUTINQ POP BC SET 3,L PLAY04: LD A,(MIDIUS+4) CP C JP NZ,PLAY05 PUSH BC LD B,4 CALL PUTINQ POP BC SET 4,L PLAY05 LD A,(MIDIUS+5) CP C JP NZ,PLAY06 PUSH BC LD B,5 CALL PUTINQ POP BC SET 5,L PLAY06 LD A,(MIDIUS+6) CP C JP NZ,PLAY07 PUSH BC LD B,6 CALL PUTINQ POP BC SET 6,L PLAY07: LD A,(MIDIUS+7) CP C JP NZ,ENDPL PUSH HL ;Put in queue LD B,7 ;IDB# CALL QWRIT POP HL SET 7,L ;END DO forever ENDPL: ;play EX DE,HL CALL PCALL RET ;############################ CHGVOC: ; given midi channel in B ; and patch in C LD A,(MIDIUS) CP B JP NZ,OFF1 ;** PUSH BC ; issue note off to queue LD A,01H LD B,0 ;** CALL RCALL ; get/load voice POP BC PUSH BC LD B,0 ;** LD A,19H CALL SCALL LD A,(PATCH) LD (VOICES),A LD A,0 CALL SCRUPD POP BC OFF1: LD A,(MIDIUS+1) CP B JP NZ,OFF2 ;** PUSH BC ; issue note off to queue LD A,01H LD B,1 ;** CALL RCALL ; get/load voice POP BC PUSH BC LD B,1 ;** LD A,19H CALL SCALL LD A,(PATCH) LD (VOICES+1),A LD A,1 CALL SCRUPD POP BC OFF2: LD A,(MIDIUS+2) CP B JP NZ,OFF3 ;** PUSH BC ; issue note off to queue LD A,01H LD B,2 ;** CALL RCALL ; get/load voice POP BC PUSH BC LD B,2 ;** LD A,19H CALL SCALL LD A,(PATCH) LD (VOICES+2),A LD A,2 CALL SCRUPD POP BC OFF3: LD A,(MIDIUS+3) CP B JP NZ,OFF4 ;** PUSH BC ; issue note off to queue LD A,01H LD B,3 ;** CALL RCALL ; get/load voice POP BC PUSH BC LD B,3 ;** LD A,19H CALL SCALL LD A,(PATCH) LD (VOICES+3),A LD A,3 CALL SCRUPD POP BC OFF4: LD A,(MIDIUS+4) CP B JP NZ,OFF5 ;** PUSH BC ; issue note off to queue LD A,01H LD B,4 ;** CALL RCALL ; get/load voice POP BC PUSH BC LD B,4 ;** LD A,19H CALL SCALL LD A,(PATCH) LD (VOICES+4),A LD A,4 CALL SCRUPD POP BC OFF5: LD A,(MIDIUS+5) CP B JP NZ,OFF6 ;** PUSH BC ; issue note off to queue LD A,01H LD B,5 ;** CALL RCALL ; get/load voice POP BC PUSH BC LD B,5 ;** LD A,19H CALL SCALL LD A,(PATCH) LD (VOICES+5),A LD A,5 CALL SCRUPD POP BC OFF6: LD A,(MIDIUS+6) CP B JP NZ,OFF7 ;** PUSH BC ; issue note off to queue LD A,01H LD B,6 ;** CALL RCALL ; get/load voice POP BC PUSH BC LD B,6 ;** LD A,19H CALL SCALL LD A,(PATCH) LD (VOICES+6),A LD A,6 CALL SCRUPD POP BC OFF7: LD A,(MIDIUS+7) CP B JP NZ,OFF8 ;** PUSH BC ; issue note off to queue LD A,01H LD B,7 ;** CALL RCALL ; get/load voice POP BC PUSH BC LD B,7 ;** LD A,19H CALL SCALL LD A,(PATCH) LD (VOICES+7),A LD A,7 CALL SCRUPD POP BC OFF8: RET ;############################ ;NOTOFF ; Given midi channel ; in B,turns off all IDB's ; for that channel NOTOFF:: LD A,(MIDIUS);** CP B JP NZ,NOFF1;** PUSH BC ; issue note off to queue LD A,01H LD B,0 ;** CALL RCALL POP BC NOFF1: LD A,(MIDIUS+1);** CP B JP NZ,NOFF2;** PUSH BC ; issue note off to queue LD A,01H LD B,1 ;** CALL RCALL POP BC NOFF2: LD A,(MIDIUS+2);** CP B JP NZ,NOFF3;** PUSH BC ; issue note off to queue LD A,01H LD B,2 ;** CALL RCALL POP BC NOFF3: LD A,(MIDIUS+3);** CP B JP NZ,NOFF4;** PUSH BC ; issue note off to queue LD A,01H LD B,3 ;** CALL RCALL POP BC NOFF4: LD A,(MIDIUS+4);** CP B JP NZ,NOFF5;** PUSH BC ; issue note off to queue LD A,01H LD B,4 ;** CALL RCALL POP BC NOFF5: LD A,(MIDIUS+5);** CP B JP NZ,NOFF6;** PUSH BC ; issue note off to queue LD A,01H LD B,5 ;** CALL RCALL POP BC NOFF6: LD A,(MIDIUS+6);** CP B JP NZ,NOFF7;** PUSH BC ; issue note off to queue LD A,01H LD B,6 ;** CALL RCALL POP BC NOFF7: LD A,(MIDIUS+7);** CP B JP NZ,NOFF8;** ; issue note off to queue LD A,01H LD B,7 ;** CALL RCALL NOFF8: RET ;########################### PORT: ; given midi channel in B ; if portamento off turns ; it on by loading idbx+5 ; with clock speed, else ; turns it off by loading ; clock speed of 0 LD A,(MIDIUS) CP B JP NZ,PORT1 LD A,(IDB0BF+5) OR A LD A,(PORTCK) JP Z,P0SET XOR A P0SET: LD (IDB0BF+5),A PORT1: LD A,(MIDIUS+1) CP B JP NZ,PORT2 LD A,(IDB1BF+5) OR A LD A,(PORTCK+1) JP Z,P1SET XOR A P1SET: LD (IDB1BF+5),A PORT2: LD A,(MIDIUS+2) CP B JP NZ,PORT3 LD A,(IDB2BF+5) OR A LD A,(PORTCK+2) JP Z,P2SET XOR A P2SET: LD (IDB2BF+5),A PORT3: LD A,(MIDIUS+3) CP B JP NZ,PORT4 LD A,(IDB3BF+5) OR A LD A,(PORTCK+3) JP Z,P3SET XOR A P3SET: LD (IDB3BF+5),A PORT4: LD A,(MIDIUS+4) CP B JP NZ,PORT5 LD A,(IDB4BF+5) OR A LD A,(PORTCK+4) JP Z,P4SET XOR A P4SET: LD (IDB4BF+5),A PORT5: LD A,(MIDIUS+5) CP B JP NZ,PORT6 LD A,(IDB5BF+5) OR A LD A,(PORTCK+5) JP Z,P5SET XOR A P5SET: LD (IDB5BF+5),A PORT6: LD A,(MIDIUS+6) CP B JP NZ,PORT7 LD A,(IDB6BF+5) OR A LD A,(PORTCK+6) JP Z,P6SET XOR A P6SET: LD (IDB6BF+5),A PORT7: LD A,(MIDIUS+7) CP B JP NZ,PORT8 LD A,(IDB7BF+5) OR A LD A,(PORTCK+7) JP Z,P7SET XOR A P7SET: LD (IDB7BF+5),A PORT8: RET ;########################### PCLK: ; given midi channel in B ; and clock speed in c ; sets portamento clock ; (PORTCK) PCLK0: LD A,(MIDIUS) CP B JP NZ,PCLK1 LD A,C LD (PORTCK),A LD A,(IDB0BF+5) OR A JP Z,PCLK1 LD A,C LD (IDB0BF+5),A PCLK1: LD A,(MIDIUS + 1) CP B JP NZ,PCLK2 LD A,C LD (PORTCK+1),A LD A,(IDB1BF+5) OR A JP Z,PCLK2 LD A,C LD (IDB1BF+5),A PCLK2: LD A,(MIDIUS + 2) CP B JP NZ,PCLK3 LD A,C LD (PORTCK+2),A LD A,(IDB2BF+5) OR A JP Z,PCLK3 LD A,C LD (IDB2BF+5),A PCLK3: LD A,(MIDIUS + 3) CP B JP NZ,PCLK4 LD A,C LD (PORTCK+3),A LD A,(IDB3BF+5) OR A JP Z,PCLK4 LD A,C LD (IDB3BF+5),A PCLK4: LD A,(MIDIUS + 4) CP B JP NZ,PCLK5 LD A,C LD (PORTCK+4),A LD A,(IDB4BF+5) OR A JP Z,PCLK5 LD A,C LD (IDB4BF+5),A PCLK5: LD A,(MIDIUS + 5) CP B JP NZ,PCLK6 LD A,C LD (PORTCK+5),A LD A,(IDB5BF+5) OR A JP Z,PCLK6 LD A,C LD (IDB5BF+5),A PCLK6: LD A,(MIDIUS + 6) CP B JP NZ,PCLK7 LD A,C LD (PORTCK+6),A LD A,(IDB6BF+5) OR A JP Z,PCLK7 LD A,C LD (IDB6BF+5),A PCLK7: LD A,(MIDIUS + 7) CP B JP NZ,PCLK8 LD A,C LD (PORTCK+7),A LD A,(IDB7BF+5) OR A JP Z,PCLK8 LD A,C LD (IDB7BF+5),A PCLK8 RET ;########################### PITBND: ; given midi channel in B ; and pitch bend value in HL ; using only seven bits of ; each ; sets pitchbend into any ; IDB with that midi channel. ; normalize from 40,00 to 0100 LD A,(PITSHT) SLA L NORM: SRL H RR L DEC A JP NZ,NORM LD DE,(PITOFF) ; now subtract to get +/- ADD HL,DE EX DE,HL LD A,(MIDIUS) CP B JP NZ,PITB1 LD HL,(DETUNE) ADD HL,DE LD (IDB0BF+3),HL PITB1: LD A,(MIDIUS+1) CP B JP NZ,PITB2 LD HL,(DETUNE+2) ADD HL,DE LD (IDB1BF+3),HL PITB2: LD A,(MIDIUS+2) CP B JP NZ,PITB3 LD HL,(DETUNE+4) ADD HL,DE LD (IDB2BF+3),HL PITB3: LD A,(MIDIUS+3) CP B JP NZ,PITB4 LD HL,(DETUNE+6) ADD HL,DE LD (IDB3BF+3),HL PITB4: LD A,(MIDIUS+4) CP B JP NZ,PITB5 LD HL,(DETUNE+8) ADD HL,DE LD (IDB4BF+3),HL PITB5: LD A,(MIDIUS+5) CP B JP NZ,PITB6 LD HL,(DETUNE+10) ADD HL,DE LD (IDB5BF+3),HL PITB6: LD A,(MIDIUS+6) CP B JP NZ,PITB7 LD HL,(DETUNE+12) ADD HL,DE LD (IDB6BF+3),HL PITB7: LD A,(MIDIUS+7) CP B JP NZ,PITB8 LD HL,(DETUNE+14) ADD HL,DE LD (IDB7BF+3),HL PITB8: RET ;########################### ;SUSTAI ; Given midi channel ; in B, and on/off in C ; sets all IDB's ; for that channel sustain ; on or off depending on veloc SUSTAI: LD A,C CP 0 JP Z,SUST0 LD C,01 ;*********************************** SUST0: LD A,(MIDIUS) CP B JP NZ,SUSTY1 ;** PUSH BC ;set IDB to sustain LD B,0H ;** LD A,12H CALL SCALL POP BC SUSTY1: LD A,(MIDIUS+1) CP B JP NZ,SUSTY2 ;** PUSH BC ;set IDB to sustain LD B,01H;** LD A,12H CALL SCALL POP BC SUSTY2: LD A,(MIDIUS+2) CP B JP NZ,SUSTY3 ;** PUSH BC ;set IDB to sustain LD B,02H;** LD A,12H CALL SCALL POP BC SUSTY3: LD A,(MIDIUS+3) CP B JP NZ,SUSTY4 ;** PUSH BC ;set IDB to sustain LD B,03H;** LD A,12H CALL SCALL POP BC SUSTY4: LD A,(MIDIUS+4) CP B JP NZ,SUSTY5 ;** PUSH BC ;set IDB to sustain LD B,04H;** LD A,12H CALL SCALL POP BC SUSTY5: LD A,(MIDIUS+5) CP B JP NZ,SUSTY6 ;** PUSH BC ;set IDB to sustain LD B,05H;** LD A,12H CALL SCALL POP BC SUSTY6: LD A,(MIDIUS+6) CP B JP NZ,SUSTY7 ;** PUSH BC ;set IDB to sustain LD B,06H;** LD A,12H CALL SCALL POP BC SUSTY7: LD A,(MIDIUS+7) CP B JP NZ,SUSTY8 ;** ;set IDB to sustain LD B,07H ;** LD A,12H CALL SCALL SUSTY8: RET ;########################### ; ; ;VOLUME ; Given midi channel ; in B, and volume in C ; sets volume for ; all IDB's for that channel VOLUME: LD A,(MIDIUS) CP B JP NZ,VOLU1 ;** PUSH BC ;set IDB volume LD B,0H ;** LD A,13H CALL SCALL POP BC ; LD A,C ; LD (VELTBL),A VOLU1: LD A,(MIDIUS+1) CP B JP NZ,VOLU2 ;** PUSH BC ;set IDB volume LD B,01H;** LD A,13H CALL SCALL POP BC ; LD A,C ; LD (VELTBL+1),A VOLU2: LD A,(MIDIUS+2) CP B JP NZ,VOLU3 ;** PUSH BC ;set IDB volume LD B,02H;** LD A,13H CALL SCALL POP BC ; LD A,C ; LD (VELTBL+2),A VOLU3: LD A,(MIDIUS+3) CP B JP NZ,VOLU4 ;** PUSH BC ;set IDB volume LD B,03H;** LD A,13H CALL SCALL POP BC ; LD A,C ; LD (VELTBL+3),A VOLU4: LD A,(MIDIUS+4) CP B JP NZ,VOLU5 ;** PUSH BC ;set IDB volume LD B,04H;** LD A,13H CALL SCALL POP BC ; LD A,C ; LD (VELTBL+4),A VOLU5: LD A,(MIDIUS+5) CP B JP NZ,VOLU6 ;** PUSH BC ;set IDB volume LD B,05H;** LD A,13H CALL SCALL POP BC ; LD A,C ; LD (VELTBL+5),A VOLU6: LD A,(MIDIUS+6) CP B JP NZ,VOLU7 ;** PUSH BC ;set IDB volume LD B,06H;** LD A,13H CALL SCALL ; LD A,C ; LD (VELTBL+6),A POP BC VOLU7: LD A,(MIDIUS+7) CP B JP NZ,VOLU8 ;** ;set IDB volume ; LD A,C ; LD (VELTBL+7),A LD B,07H ;** LD A,13H CALL SCALL VOLU8: RET ;########################### ; ;AMSPMS ; Given midi channel ; in B, and pms/ams in C ; sets it for ; all IDB's for that channel AMSPMS: LD A,(MIDIUS) CP B JP NZ,AMSPM1 ;** PUSH BC ;set IDB volume LD B,0H ;** LD A,18H CALL SCALL POP BC AMSPM1: LD A,(MIDIUS+1) CP B JP NZ,AMSPM2 ;** PUSH BC ;set IDB volume LD B,01H;** LD A,18H CALL SCALL POP BC AMSPM2: LD A,(MIDIUS+2) CP B JP NZ,AMSPM3 ;** PUSH BC ;set IDB volume LD B,02H;** LD A,18H CALL SCALL POP BC AMSPM3: LD A,(MIDIUS+3) CP B JP NZ,AMSPM4 ;** PUSH BC ;set IDB volume LD B,03H;** LD A,18H CALL SCALL POP BC AMSPM4: LD A,(MIDIUS+4) CP B JP NZ,AMSPM5 ;** PUSH BC ;set IDB volume LD B,04H;** LD A,18H CALL SCALL POP BC AMSPM5: LD A,(MIDIUS+5) CP B JP NZ,AMSPM6 ;** PUSH BC ;set IDB volume LD B,05H;** LD A,18H CALL SCALL POP BC AMSPM6: LD A,(MIDIUS+6) CP B JP NZ,AMSPM7 ;** PUSH BC ;set IDB volume LD B,06H;** LD A,18H CALL SCALL POP BC AMSPM7: LD A,(MIDIUS+7) CP B JP NZ,AMSPM8 ;** ;set IDB volume LD B,07H ;** LD A,18H CALL SCALL AMSPM8: RET ;########################### ; ;BRILLI ; Given midi channel ; in B, and brilliance in C ; sets it for system ; if midi channel applies ; to any midi defined in ; this slave. BRILLI: LD D,8 LD HL,MIDIUS LD A,B BRILL1: CP (HL) JP NZ,BRILL0 LD A,10H CALL SCALL RET BRILL0: