5   REM
10  COLOR 15,1:CLS
15  PRINT"Yamaha TX81Z/DX11  Librarian / Editor":PRINT
25  COLOR 4,7: PRINT"5/28/88  D.O.Bowker  AT&T Bell Labs  (201) 949-2607":PRINT
30 COLOR 4,0: PRINT"Major Extensions/Enhancements 5/6/89  D.Henderson  AT&T Bell Labs (201)949-4591": PRINT
35 COLOR 4,6: PRINT "DX11 Extensions 5/13/89  S.Michelson  BellCore (BCR) (201) 758-5238"
40  COLOR 15,1:PRINT:PRINT"Please wait..initializing"
45  :
50  FOR I=1 TO 1500: NEXT
55  :
60 TXSEL=1	: REM ...1= default= TX81Z      0=dx11......
65 STATPORT = 817:   DATAPORT=816
70 :
75 REM ...KEY OFF:KEY 10,"system"+CHR$(13)
80 OUT STATPORT,255:OUT STATPORT,63 : REM *sent FF 3F (reset MPU & UART mode..)
85 GOSUB 4955
90 DIM PAR%(200),PARA%(200),PARB%(200)
95 DIM P$(200),P2$(200),PTABL(97,5),CTABL(92,5)
100 DIM NOTES$(12):NOTES$(0)="C":NOTES$(1)="C#":NOTES$(2)="D":NOTES$(3)="D#":NOTES$(4)="E":NOTES$(5)="F":NOTES$(6)="F#":NOTES$(7)="G":NOTES$(8)="G#":NOTES$(9)="A":NOTES$(10)="A#":NOTES$(11)="B"
105 GOSUB 575:REM load ptabl() and ctabl() from DATA statements
110 REM  set up default lib file names....
115 VOICDEF$= "default.pat": PERFDEF$ = "default.cmb"
120 VOICNAM$= VOICDEF$:  PERFNAM$= PERFDEF$
125 CHAN% = 0: REM .. MIDI channel (0 = chan 1)
130 NOTEOCT = 2: NOTELEN = 20 : NOTEVEL = 70: REM -PLAY octave,dur,velocity
135 NULL$=CHR$(0)
140 :
145 GOSUB 5435: REM  read user's defaults if any..
150 REM beep
155 :
160 ON ERROR GOTO 165: GOTO 190
165 REM error handler.....................
170 PRINT:COLOR 15,12:PRINT"<<**** ERROR!! ****>>";:COLOR 15,1:PRINT
175 BEEP:FOR I=1 TO 500: NEXT : RESUME NEXT
180 :
185 :
190 WHERE=1:COLOR 4,1:CLS:PRINT" Yamaha TX81Z/DX11 Editor/Librarian":PRINT
195 COLOR 15,1
200 PRINT"show patches in file  (a)            show performances in file   (h)"
205 PRINT"read patch from TX/DX (b)            read performance from TX/DX (i)"
210 PRINT"write patch to TX/DX  (c)            write performance to TX/DX  (j)"
215 PRINT"display patch on CRT  (d)            display performance on CRT  (k)"
220 PRINT"rand patch - scratch  (e)            edit a TX/DX performance    (l)"
225 PRINT"rand patch - seed     (f)            edit a TX/DX patch          (m)"
230 PRINT"rand patch - blend    (g)":PRINT
235 PRINT"select patch lib. . . (n)            select perf lib . . . . . . (o)"
240 PRINT"patch utilities . . . (p)            set midi i/o channel. . . . (r)"
245 PRINT"send midi notes . . . (s)            send patch change command. .(t)"
250 PRINT"read 32 Ibank patches.(v)            send 32 patches to Ibank . .(w)"
255 PRINT"Directory .   . . . . (x)"
260 PRINT"memory protect ON . . (A)            memory protect OFF . . . . .(B)"
265 PRINT"Toggle TX - DX select (C)
270 PRINT"Exit............................................................ (Q)"
275 :
280 PRINT:PRINT"MidiChan: "CHAN% +1
285 PRINT"current PatchLib: "VOICNAM$"         current PerfLib: "PERFNAM$
290 PRINT"mode: ";: IF TXSEL=1 THEN PRINT"TX"  ELSE PRINT"DX"
295 RESP$=INKEY$:IF LEN(RESP$)=0 THEN 295
300 REM ..dont need this..GOSUB 1540:REM set MX-8 for PC <<==>> TX81Z link
305 PRINT
310 IF RESP$="p" THEN GOSUB 1390:GOTO 190
315 IF RESP$="g" THEN GOSUB 2605:GOTO 190
320 IF RESP$="k" THEN GOSUB 2010:GOTO 190
325 IF RESP$="m" THEN GOSUB 2840:GOTO 190
330 IF RESP$="l" THEN GOSUB 3520:GOTO 190
335 IF RESP$="a" THEN VOICE$=VOICNAM$: GOSUB 5505 :GOTO 190: REM *** 990:GOTO 340
340 IF RESP$="b" THEN GOSUB 825:GOTO 190
345 IF RESP$="h" THEN GOSUB 450:GOTO 190
350 IF RESP$="e" THEN GOSUB 2295:GOTO 190
355 IF RESP$="i" THEN GOSUB 2070:GOTO 190
360 IF RESP$="c" THEN GOSUB 5640:GOTO 190: REM *** 2150:GOTO 340
365 IF RESP$="j" THEN GOSUB 2195:GOTO 190
370 IF RESP$="f" THEN GOSUB 2440:GOTO 190
375 IF RESP$="d" THEN GOSUB 1205:GOTO 190
380 IF RESP$="n" THEN GOSUB 4395:GOTO 190
385 IF RESP$="o" THEN GOSUB 4425:GOTO 190
390 IF RESP$="r" THEN GOSUB 4455:GOTO 190
395 IF RESP$="s" THEN GOSUB 4480:GOTO 190
400 IF RESP$="t" THEN GOSUB 4665:GOTO 190
405 IF RESP$="v" THEN GOSUB 4975:GOTO 190
410 IF RESP$="w" THEN GOSUB 5245:GOTO 190
415 IF RESP$="x" THEN GOSUB 5480:GOTO 190
420 IF RESP$="A" THEN GOSUB 4885: BEEP: GOTO 190:REM ..mem prot on
425 IF RESP$="B" THEN GOSUB 4860: BEEP: GOTO 190:REM .."   "   off
430 IF RESP$="C" THEN GOSUB 5805  : GOTO 190
435 IF RESP$="Q" THEN GOSUB 5390: GOSUB 805:ON ERROR GOTO 0:END
440 GOTO 295 :REM keep looping, waiting for a response..
445 :
450 REM LIST PERFORMANCES IN current perf lib file ...
455 PRINT:PRINT"PERFORMANCES IN -->" PERFNAM$
460 PRINT "list to (s)creen-only  or  (p)rinter & screen ?"
465 STDOUT$=INKEY$: IF LEN(STDOUT$)=0 THEN GOTO 465
470 PRINT "<hit any key to abort>"
475 OPEN "R",#1,PERFNAM$,122:RN=1
480 FOR I%=1 TO 121:FIELD#1,(I%*1) AS OFFSET$,1 AS P$(I%):NEXT I%
485 LRN=CINT(LOF(1)/122):PRINT"Total Performances:";LRN:PRINT
490 RLIM=1+INT(LRN/4)
495 FOR RN=1 TO RLIM
500 FOR CLM=1 TO 4
505 IF(RN+((CLM-1)*RLIM))>LRN THEN GOTO 540 ELSE GET#1,RN+((CLM-1)*RLIM)
510 FOR I%=1 TO 121:PAR%(I%)=CVI(P$(I%)+NULL$):NEXT I%
515 PRINT USING"####";RN+((CLM-1)*RLIM);:PRINT": ";
520 IF STDOUT$="p" THEN LPRINT USING"####";RN+((CLM-1)*RLIM);:LPRINT": ";
525 FOR I%=111 TO 120:PRINT CHR$(PAR%(I%));:NEXT I%:PRINT"    ";
530 IF STDOUT$="p" THEN FOR I%=111 TO 120:LPRINT CHR$(PAR%(I%));:NEXT I%:LPRINT"    ";
535 RESP$=INKEY$:IF LEN(RESP$)<>0 THEN 550
540 NEXT CLM:NEXT RN
545 CLOSE #1
550 PRINT: PRINT"<hit any key to continue>"
555 RESP$=INKEY$:IF LEN(RESP$)= 0 THEN 555
560 RETURN 190
565 :
570 :
575 REM data TX81Z patch table
580 DATA 84,99,0,3,15,58,99,0,3,19,71,99,0,3,23,45,99,0,3,27:REM out level
585 DATA 26,1,0,4,15,16,1,0,4,19,21,1,0,4,23,11,1,0,4,27:REM freq.type
590 DATA 27,7,0,5,15,17,7,0,5,19,22,7,0,5,23,12,7,0,5,27:REM fix range
595 DATA 85,63,0,6,15,59,63,0,6,19,72,63,0,6,23,46,63,0,6,27:REM freq.coarse
600 DATA 28,15,0,7,15,18,15,0,7,19,23,15,0,7,23,13,15,0,7,27:REM freq.fine
605 DATA 86,6,-3,8,15,60,6,-3,8,19,73,6,-3,8,23,47,6,-3,8,27:REM detune
610 DATA 29,7,1,9,15,19,7,1,9,19,24,7,1,9,23,14,7,1,9,27:REM waveform
615 DATA 74,31,0,10,15,48,31,0,10,19,61,31,0,10,23,35,31,0,10,27:REM attack rate
620 DATA 75,31,0,11,15,49,31,0,11,19,62,31,0,11,23,36,31,0,11,27:REM decay1 rate
625 DATA 78,15,0,12,15,52,15,0,12,19,65,15,0,12,23,39,15,0,12,27:REM decay1 lvl
630 DATA 76,31,0,13,15,50,31,0,13,19,63,31,0,13,23,37,31,0,13,27:REM decay2 rate
635 DATA 77,15,0,14,15,51,15,0,14,19,64,15,0,14,23,38,15,0,14,27:REM release rat
640 DATA 30,3,0,15,15,20,3,0,15,19,25,3,0,15,23,15,3,0,15,27:REM eg shift
645 DATA 80,3,0,16,15,54,3,0,16,19,67,3,0,16,23,41,3,0,16,27:REM scale rate
650 DATA 79,99,0,17,15,53,99,0,17,19,66,99,0,17,23,40,99,0,17,27:REM scale level
655 DATA 82,1,0,18,15,56,1,0,18,19,69,1,0,18,23,43,1,0,18,27:REM scale on/off
660 DATA 81,7,0,19,15,55,7,0,19,19,68,7,0,19,23,42,7,0,19,27:REM scale eg bias
665 DATA 83,7,0,20,15,57,7,0,20,19,70,7,0,20,23,44,7,0,20,27:REM scale key vel
670 DATA 87,7,1,2,46,88,7,0,3,46,94,3,0,4,46,93,1,0,4,63:REM alg,feed,wave,sync
675 DATA 89,99,0,5,46,90,99,0,5,63,92,99,0,6,46,96,3,0,6,63:REM LFO stuff
680 DATA 91,99,0,7,46,95,7,0,7,63,98,1,0,8,46,97,48,24,8,63:REM LFO, functions
685 DATA 100,1,0,9,46,31,7,0,9,63,101,99,0,10,46,99,12,0,10,63:REM more fnctns
690 DATA 102,99,0,11,46,108,99,0,11,63,32,99,0,12,46,109,99,0,12,63:REM more fs
695 DATA 33,99,0,13,46,111,99,0,13,63,106,99,0,14,46,110,99,-50,14,63:REM more fs
700 DATA 107,99,0,15,46:REM that's all folks!
705 FOR I=1 TO 97:FOR J=1 TO 5:READ PTABL(I,J):NEXT J:NEXT I
710 REM data TX81Z performance table
715 DATA 11,8,0,4,15,23,8,0,4,22,35,8,0,4,29,47,8,0,4,36,59,8,0,4,43,71,8,0,4,50,83,8,0,4,57,95,8,0,4,64:REM max notes
720 DATA 12,159,1,5,15,24,159,1,5,22,36,159,1,5,29,48,159,1,5,36,60,159,1,5,43,72,159,1,5,50,84,159,1,5,57,96,159,1,5,64:REM voice number
725 DATA 14,16,1,6,15,26,16,1,6,22,38,16,1,6,29,50,16,1,6,36,62,16,1,6,43,74,16,1,6,50,86,16,1,6,57,98,16,1,6,64:REM MIDI receive channel
730 DATA 15,127,1,7,15,27,127,1,7,22,39,127,1,7,29,51,127,1,7,36,63,127,1,7,43,75,127,1,7,50,87,127,1,7,57,99,127,1,7,64:REM lower note limit
735 DATA 16,127,1,8,15,28,127,1,8,22,40,127,1,8,29,52,127,1,8,36,64,127,1,8,43,76,127,1,8,50,88,127,1,8,57,100,127,1,8,64:REM upper note limit
740 DATA 17,14,-7,9,15,29,14,-7,9,22,41,14,-7,9,29,53,14,-7,9,36,65,14,-7,9,43,77,14,-7,9,50,89,14,-7,9,57,101,14,-7,9,64:REM detune
745 DATA 18,48,-24,10,15,30,48,-24,10,22,42,48,-24,10,29,54,48,-24,10,36,66,48,-24,10,43,78,48,-24,10,50,90,48,-24,10,57,102,48,-24,10,64:REM note shift
750 DATA 19,99,0,11,15,31,99,0,11,22,43,99,0,11,29,55,99,0,11,36,67,99,0,11,43,79,99,0,11,50,91,99,0,11,57,103,99,0,11,64:REM volume
755 DATA 20,3,0,12,15,32,3,0,12,22,44,3,0,12,29,56,3,0,12,36,68,3,0,12,43,80,3,0,12,50,92,3,0,12,57,104,3,0,12,64:REM output assignments
760 DATA 21,3,0,13,15,33,3,0,13,22,45,3,0,13,29,57,3,0,13,36,69,3,0,13,43,81,3,0,13,50,93,3,0,13,57,105,3,0,13,64:REM LFO select
765 DATA 22,1,0,14,15,34,1,0,14,22,46,1,0,14,29,58,1,0,14,36,70,1,0,14,43,82,1,0,14,50,94,1,0,14,57,106,1,0,14,64:REM microtune on/off
770 DATA 107,12,0,16,15,108,1,0,17,15,109,3,0,17,29,110,11,1,16,29:REM extras
775 FOR I=1 TO 92:FOR J=1 TO 5:READ CTABL(I,J):NEXT J:NEXT I
780 RETURN
785 REM switch MX-8 to correct set-up for TX81Z Librarian
790 RETURN: OUT STATPORT,255:OUT STATPORT,63:FOR I%=1 TO 500:JUNK=INP(DATAPORT):NEXT I%
795 OUT DATAPORT,192+15:OUT DATAPORT,19:REM MX-8 is on MIDI chan.15, TX81Z Libr. is prog.19
800 RETURN
805 REM switch MX-8 to set-up for Keyboard to play TX81Z
810 RETURN: OUT STATPORT,255:OUT STATPORT,63:FOR I%=1 TO 500:JUNK=INP(DATAPORT):NEXT I%
815 OUT DATAPORT,192+15:OUT DATAPORT,17:REM MX-8 is on MIDI chan.15, set-up is prog.17
820 RETURN
825 REM ***** READ PATCH (from TX81Z) and ADD TO PatchLib file  ******
830 OPEN "R",#1,VOICNAM$,129:FOR I%=1 TO 128:FIELD#1,(I%*1) AS OFFSET$,1 AS P$(I%):NEXT I%
835 GOSUB 1025 :PRINT"please wait..."
840 GOSUB 4955
845 OUT STATPORT,255:OUT STATPORT,63
850 FOR I=1 TO 1000:JUNK=INP(DATAPORT):NEXT I
855 IF TXSEL=0 GOTO 875
860 PRINT"Select patch on TX81Z, then hit any key."
865 RESP$=INKEY$: IF LEN(RESP$)=0 THEN GOTO 865
870 GOSUB 4955: GOSUB 4800: GOSUB 4955: GOSUB 4785: GOTO 885 REM ..toggle data +,-
875 REM ...do DX single patch read
880 PRINT" Ready to read DX patch. Hit DX patch button now"
885 A$=INKEY$: IF LEN(A$)<>0 THEN GOTO 1035
890 IF INP(DATAPORT)<>240 GOTO 885
895 IF INP(DATAPORT)<>67 GOTO 885
900 IF INP(DATAPORT)<>CHAN% GOTO 885
905 IF INP(DATAPORT)<>126 GOTO 885
910 IF INP(DATAPORT)<>0 GOTO 885
915 IF INP(DATAPORT)<>33 GOTO 885
920 FOR I%=1 TO 34
925 PAR%(I%)=INP(DATAPORT)
930 NEXT I%
935 IF INP(DATAPORT)<>247 GOTO 990
940 IF INP(DATAPORT)<>240 GOTO 940
945 IF INP(DATAPORT)<>67 GOTO 940
950 IF INP(DATAPORT)<>CHAN% GOTO 940
955 IF INP(DATAPORT)<>3 GOTO 940
960 IF INP(DATAPORT)<>0 GOTO 940
965 IF INP(DATAPORT)<>93 GOTO 940
970 FOR I%=35 TO 128
975 PAR%(I%)=INP(DATAPORT)
980 NEXT I%
985 IF INP(DATAPORT)=247 GOTO 1000
990 PRINT"NO END OF DATA FROM SYNTH - RETURNING TO MAIN MENU"
995 FOR I%=1 TO 500:NEXT I%:CLOSE #1:RETURN 190
1000 FOR I%=1 TO 128:RSET P$(I%)=MKI$(PAR%(I%)):NEXT I%
1005 FOR I%=112 TO 121:PRINT CHR$(PAR%(I%));:NEXT I%:PRINT
1010 PUT #1,LRN
1015 FOR I%=1 TO 500:NEXT I%
1020 PRINT"Patch Dump Completed...Now ";LRN;" total patches in-->"VOICNAM$: CLOSE #1:RETURN 190
1025 REM subroutine to count number of records in current voice lib
1030 LRN=CINT(LOF(1)/129)+1
1035 RETURN
1040 REM subroutine to calculate two's-compliment checksum for random patches
1045 CHSUM0=0:CHSUM1=0
1050 FOR I=1 TO 33:CHSUM0=CHSUM0+PAR%(I):NEXT I
1055 FOR I=35 TO 127:CHSUM1=CHSUM1+PAR%(I):NEXT I
1060 CHSUM0=128*((CHSUM0/128)-(INT(CHSUM0/128)))
1065 CHSUM1=128*((CHSUM1/128)-(INT(CHSUM1/128)))
1070 CHSUM0=128-CHSUM0:CHSUM1=128-CHSUM1
1075 PAR%(34)=CHSUM0:PAR%(128)=CHSUM1
1080 RETURN
1085 REM WRITE A LIBRARY PATCH TO THE SYNTH...
1090 WHERE=0
1095 OPEN "R",#1,VOICNAM$,129:FOR I%=1 TO 128:FIELD#1,(I%*1) AS OFFSET$,1 AS P$(I%):NEXT I%
1100 LRN=CINT(LOF(1)/129)
1105 PRINT"enter patch record number to write to TX81Z (1 -";LRN;")";:INPUT CODE
1110 IF(CODE>0 AND CODE <=LRN)THEN GET #1,CODE ELSE PRINT"VALUE OUT OF RANGE":BEEP:GOTO 1185
1115 INPUT"select TX81Z (destination) patch ,then press return ";RESP$
1120 FOR I%=1 TO 128:PAR%(I%)=CVI(P$(I%)+NULL$):NEXT I%
1125 GOSUB 1580
1130 OUT STATPORT,255
1135 OUT STATPORT,63
1140 FOR I%=1 TO 1000:JUNK%=INP(DATAPORT):NEXT I%
1145 OUT DATAPORT,240:OUT DATAPORT,67:OUT DATAPORT,CHAN%:OUT DATAPORT,126:OUT DATAPORT,0:OUT DATAPORT,33
1150 FOR I%=1 TO 34:OUT DATAPORT,PAR%(I%):NEXT I%:OUT DATAPORT,247
1155 OUT DATAPORT,240:OUT DATAPORT,67:OUT DATAPORT,CHAN%:OUT DATAPORT,3:OUT DATAPORT,0:OUT DATAPORT,93
1160 FOR I%=35 TO 128:OUT DATAPORT,PAR%(I%):NEXT I%:OUT DATAPORT,247
1165 IF(WHERE=4 OR WHERE=5)THEN CLOSE#1:RETURN
1170 PRINT"Patch Name:";
1175 FOR I%=112 TO 121:PRINT CHR$(PAR%(I%));:NEXT I%:PRINT
1180 CLOSE#1: REM GOSUB 1640:REM set MX-8 to keyboard ==>> TX81Z
1185 IF WHERE=1 THEN RETURN 2390
1190 IF WHERE=2 THEN RETURN 2770
1195 IF WHERE=3 THEN RETURN 2565
1200 RETURN 190
1205 REM subroutine to display patch parameter values ****
1210 PRINT:PRINT:OPEN "R",#1,VOICNAM$,129:LRN=CINT(LOF(1)/129)
1215 PRINT"enter patch record number for display ( 1 -";LRN;")";:INPUT CODE
1220 IF(CODE>0 AND CODE<=LRN)THEN GOTO 1225 ELSE PRINT "VALUE OUT OF RANGE":BEEP:GOTO 1260
1225 FOR I%=1 TO 128:FIELD#1,(I%*1) AS OFFSET$,1 AS P$(I%):NEXT I%
1230 GET #1,CODE
1235 FOR I%=1 TO 128:PAR%(I%)=CVI(P$(I%)+NULL$):NEXT I%:CLOSE #1
1240 GOSUB 1595:REM draw patch table
1245 GOSUB 1660:REM fill in values
1250 LOCATE 21,1:PRINT:COLOR 15,1:PRINT"(any key to continue)";
1255 X$=INKEY$:IF(LEN(X$)=0)THEN 1255
1260 RETURN 190
1265 REM rotine to transfer patches from one file to current PatchLib
1270 PRINT"enter SOURCE patch file name";:INPUT FILE$
1275 OPEN "R",#1,FILE$,129:FOR I%=1 TO 128:FIELD#1,(I%*1) AS OFFSET$,1 AS P$(I%):NEXT I%
1280 LRN=CINT(LOF(1)/129):PRINT"total patches in";FILE$;" = ";LRN
1285 PRINT"enter patch record number to write to TX81Z (1 -";LRN;")";:INPUT CODE
1290 IF(CODE>0 AND CODE <=LRN)THEN GET #1,CODE ELSE PRINT"VALUE OUT OF RANGE":BEEP: RETURN 190
1295 GOSUB 785:GOSUB 1115
1300 GOSUB 805
1305 GOTO 2390
1310 :
1315 REM display patches from a library file
1320 PRINT"enter patch file name for listing";:INPUT VOICE$
1325 GOSUB 5505
1330 RETURN
1335 :
1340 REM display bytes in patch file record
1345 PRINT"enter patch file name:";:INPUT FILE$
1350 PRINT:PRINT:OPEN "R",#1,FILE$,129:INPUT"enter patch record number for display";CODE
1355 FOR I=1 TO 128:FIELD#1,(I*1) AS OFFSET$,1 AS P$(I):NEXT I
1360 GET #1,CODE:FOR I=1 TO 128:PAR%(I)=CVI(P$(I)+NULL$):NEXT I:CLOSE #1
1365 CLS:COLOR 4,1:PRINT"Name:";:FOR I=112 TO 121:PRINT CHR$(PAR%(I));:NEXT I:PRINT
1370 FOR I=1 TO 16:LOCATE I+2,1:FOR J=1 TO 8:K=(((I-1)*8)+J):PRINT USING"###";K;:PRINT":";:PRINT USING"###";PAR%(K);:PRINT"  ";:NEXT J:NEXT I
1375 PRINT:COLOR 15,1:PRINT"(any key to continue)";
1380 X$=INKEY$:IF(LEN(X$)=0)THEN 1380
1385 RETURN 1395
1390 :
1395 WHERE=5:CLS:PRINT:PRINT
1400 PRINT"                     PATCH UTILITY MENU":PRINT
1405 PRINT"send a patch from specified patch lib file to TX/DX          (a)"
1410 PRINT"list patches residing in specified patch lib file            (b)"
1415 PRINT"show bytes for specified patch - in specified lib file       (c)"
1420 PRINT"copy patch(es) from current patch lib to another patch lib   (d)"
1425 PRINT
1430 PRINT"QUIT this utility .....(q)"
1435 PRINT:PRINT
1440 RESP$=INKEY$:IF LEN(RESP$)=0 THEN 1440
1445 IF RESP$="a" THEN GOSUB 1265:GOTO 1390
1450 IF RESP$="q" THEN RETURN 190
1455 IF RESP$="b" THEN GOSUB 1315:GOTO 1390
1460 IF RESP$="c" THEN GOSUB 1340:GOTO 1390
1465 IF RESP$="d" THEN GOSUB 1475:GOTO 1390
1470 GOTO 1390
1475 REM routine to transfer patches from current patch-lib to other
1480 PRINT"destination patch file:";:INPUT FILE$
1485 OPEN "R",#1,FILE$,129:FOR I%=1 TO 128:FIELD#1,(I%*1) AS OFFSET$,1 AS P$(I%):NEXT I%
1490 LRN=CINT(LOF(1)/129):PRINT"total patches in ";FILE$;" = ";LRN
1495 FILE2$=VOICNAM$:OPEN "R",#2,FILE2$,129:FOR I%=1 TO 128:FIELD#2,(I%*1) AS OFFSET$,1 AS P2$(I%):NEXT I%
1500 LRN2=CINT(LOF(2)/129):PRINT"total patches in ";FILE2$;" = ";LRN2
1505 PRINT"enter STARTing patch# for <";VOICNAM$;"> to <";FILE$;"> patch copy: "
1510 INPUT STPAT
1515 PRINT"enter ENDing patch# for <";VOICNAM$;"> to <";FILE$;"> patch copy: "
1520 INPUT ENDPAT
1525 IF(ENDPAT>LRN2 OR ENDPAT<STPAT)THEN BEEP:BEEP:RETURN
1530 FOR CODE=STPAT TO ENDPAT
1535 GET #2,CODE
1540 FOR I%=1 TO 128:PAR%(I%)=CVI(P2$(I%)+NULL$):NEXT I%
1545 FOR I%=1 TO 128:RSET P$(I%)=MKI$(PAR%(I%)):NEXT I%
1550 LRN=LRN+1:PUT #1,LRN
1555 NEXT CODE
1560 PRINT"Now ";LRN;" total patches in ";FILE$
1565 FOR I=1 TO 300: NEXT I
1570 CLOSE #1:CLOSE #2
1575 RETURN
1580 REM ROUTINE TO FLUSH ACCUMULATED DATA FROM PORT ***
1585 FOR I%=1 TO 3000:JUNK%=INP(DATAPORT):NEXT I%
1590 RETURN
1595 REM subroutine to draw patch table
1600 CLS:LOCATE 1,1
1605 PRINT"Name: ";
1610 COLOR 15,1:LOCATE 2,15:PRINT"op1";:LOCATE 2,19:PRINT"op2";:LOCATE 2,23:PRINT"op3";:LOCATE 2,27:PRINT"op4";
1615 LOCATE 3,1:PRINT"output level:";:LOCATE 4,4:PRINT"freq.type:";:LOCATE 5,4:PRINT"fix range:";:LOCATE 6,2:PRINT"freq.coarse:";:LOCATE 7,4:PRINT"freq.fine:";:LOCATE 8,7:PRINT"detune:";:LOCATE 9,5:PRINT"waveform:";
1620 LOCATE 10,2:PRINT"attack rate:";:LOCATE 11,1:PRINT"decay 1 rate:";:LOCATE 12,1:PRINT"decay 1 levl:";:LOCATE 13,1:PRINT"decay 2 rate:";:LOCATE 14,1:PRINT"release rate:";:LOCATE 15,5:PRINT"eg shift:";
1625 LOCATE 16,3:PRINT"scale rate:";:LOCATE 17,2:PRINT"scale level:";:LOCATE 18,1:PRINT"scale on/off:";:LOCATE 19,1:PRINT"scale egbias:";:LOCATE 20,1:PRINT"scale keyvel:";
1630 LOCATE 2,35:PRINT"Algorithm:";:LOCATE 3,36:PRINT"Feedback:";:LOCATE 4,32:PRINT"LFO waveform:";:LOCATE 4,57:PRINT"sync:";:LOCATE 5,39:PRINT"speed:";:LOCATE 5,56:PRINT"delay:";
1635 LOCATE 6,31:PRINT"amp mod.depth:";:LOCATE 6,57:PRINT"sens:";:LOCATE 7,31:PRINT"pch mod.depth:";:LOCATE 7,57:PRINT"sens:";:LOCATE 8,40:PRINT"mode:";:LOCATE 8,56:PRINT"mid C:";
1640 LOCATE 9,34:PRINT"portamento:";:LOCATE 9,52:PRINT"rvrb rate:";:LOCATE 10,34:PRINT"porta time:";:LOCATE 10,53:PRINT"pb range:";:LOCATE 11,38:PRINT"FC vol:";:LOCATE 11,53:PRINT"BC pitch:";
1645 LOCATE 12,36:PRINT"FC pitch:";:LOCATE 12,55:PRINT"BC amp:";:LOCATE 13,38:PRINT"FC amp:";:LOCATE 13,52:PRINT"BC egbias:";
1650 LOCATE 14,36:PRINT"MW pitch:";:LOCATE 14,53:PRINT"BC pbias:";:LOCATE 15,38:PRINT"MW amp:";
1655 RETURN
1660 REM subroutine to fill in parameter values
1665 LOCATE 1,7:COLOR 4,1:FOR I%=112 TO 121:PRINT CHR$(PAR%(I%));:NEXT I%:PRINT
1670 FOR I=1 TO 4:LOCATE PTABL(I,4),PTABL(I,5):PRINT PAR%(PTABL(I,1))+PTABL(I,3);:NEXT I
1675 FOR I=5 TO 8:LOCATE PTABL(I,4),PTABL(I,5):IF PAR%(PTABL(I,1))=0 THEN PRINT"RTO"; ELSE PRINT"FXD";
1680 NEXT I
1685 FOR I=9 TO 48:LOCATE PTABL(I,4),PTABL(I,5):PRINT PAR%(PTABL(I,1))+PTABL(I,3);:NEXT I
1690 FOR I=49 TO 52:LOCATE PTABL(I,4),PTABL(I,5)
1695 IF(PAR%(PTABL(I,1))=0)THEN PRINT "off";
1700 IF(PAR%(PTABL(I,1))=1)THEN PRINT "48 ";
1705 IF(PAR%(PTABL(I,1))=2)THEN PRINT "24 ";
1710 IF(PAR%(PTABL(I,1))=3)THEN PRINT "12 ";
1715 NEXT I:FOR I=53 TO 60:LOCATE PTABL(I,4),PTABL(I,5):PRINT PAR%(PTABL(I,1))+PTABL(I,3);:NEXT I
1720 FOR I=61 TO 64:LOCATE PTABL(I,4),PTABL(I,5):IF PAR%(PTABL(I,1))=0 THEN PRINT"off"; ELSE PRINT"on";
1725 NEXT I
1730 FOR I=65 TO 74:LOCATE PTABL(I,4),PTABL(I,5):PRINT PAR%(PTABL(I,1))+PTABL(I,3);:NEXT I
1735 LOCATE PTABL(75,4),PTABL(75,5):IF PAR%(PTABL(75,1))=0 THEN PRINT"sin";
1740 IF PAR%(PTABL(75,1))=1 THEN PRINT"sqr";
1745 IF PAR%(PTABL(75,1))=2 THEN PRINT"tri";
1750 IF PAR%(PTABL(75,1))=3 THEN PRINT"s/h";
1755 LOCATE PTABL(76,4),PTABL(76,5):IF PAR%(PTABL(76,1))=0 THEN PRINT"off"; ELSE PRINT"on";
1760 FOR I=77 TO 82:LOCATE PTABL(I,4),PTABL(I,5):PRINT PAR%(PTABL(I,1))+PTABL(I,3);:NEXT I
1765 LOCATE PTABL(83,4),PTABL(83,5):IF PAR%(PTABL(83,1))=0 THEN PRINT"PLY"; ELSE PRINT"UNI";
1770 LOCATE PTABL(85,4),PTABL(85,5):IF PAR%(PTABL(85,1))=0 THEN PRINT"off"; ELSE PRINT"full";
1775 FOR I=86 TO 97:LOCATE PTABL(I,4),PTABL(I,5):PRINT PAR%(PTABL(I,1))+PTABL(I,3);:NEXT I
1780 LOCATE PTABL(84,4),PTABL(84,5):GURN0=(PAR%(PTABL(84,1)))/12:GURN1=INT(GURN0):GURN2=CINT((GURN0-GURN1)*12):PRINT NOTES$(GURN2);GURN1+1;
1785 RETURN
1790 REM subroutine to draw performance table
1795 CLS:LOCATE 1,1:PRINT"Name:";
1800 LOCATE 3,16:PRINT"1";:LOCATE 3,23:PRINT"2";:LOCATE 3,30:PRINT"3";:LOCATE 3,37:PRINT"4";:LOCATE 3,44:PRINT"5";:LOCATE 3,51:PRINT"6";:LOCATE 3,58:PRINT"7";:LOCATE 3,65:PRINT"8";
1805 LOCATE 4,4:PRINT"MAX NOTES:";:LOCATE 5,1:PRINT"VOICE NUMBER:";:LOCATE 6,1:PRINT"MIDI RECEIVE:";
1810 LOCATE 7,5:PRINT"LOW NOTE:";:LOCATE 8,4:PRINT"HIGH NOTE:";:LOCATE 9,7:PRINT"DETUNE:";
1815 LOCATE 10,3:PRINT"NOTE SHIFT:";:LOCATE 11,7:PRINT"VOLUME:";:LOCATE 12,7:PRINT"OUTPUT:";
1820 LOCATE 13,3:PRINT"LFO SELECT:";:LOCATE 14,4:PRINT"MICROTUNE:";
1825 LOCATE 16,2:PRINT"MICRO TABLE:";:LOCATE 16,24:PRINT"KEY:";
1830 LOCATE 17,2:PRINT"ASSIGN MODE:";:LOCATE 17,21:PRINT"EFFECT:";
1835 RETURN
1840 REM subroutine to fill in performance data for display
1845 LOCATE 1,7:COLOR 4,1:FOR I%=111 TO 120:PRINT CHR$(PAR%(I%));:NEXT I%:PRINT
1850 FOR I=1 TO 8:LOCATE CTABL(I,4),CTABL(I,5):PRINT PAR%(CTABL(I,1))+CTABL(I,3);:NEXT I
1855 FOR I=9 TO 16:LOCATE CTABL(I,4),CTABL(I,5)
1860 JUNK=128*(PAR%(CTABL(I,1))):JUNK=JUNK+PAR%(CTABL(I,1)+1):JUNK0=INT(JUNK/32):JUNK=JUNK+1
1865 IF JUNK0=0 THEN CRAP$="I"
1870 IF JUNK0=1 THEN CRAP$="A":JUNK=JUNK-32
1875 IF JUNK0=2 THEN CRAP$="B":JUNK=JUNK-64
1880 IF JUNK0=3 THEN CRAP$="C":JUNK=JUNK-96
1885 IF JUNK0=4 THEN CRAP$="D":JUNK=JUNK-128
1890 PRINT CRAP$;JUNK;:NEXT I
1895 FOR I=17 TO 24:LOCATE CTABL(I,4),CTABL(I,5):IF(PAR%(CTABL(I,1))<16)THEN PRINT PAR%(CTABL(I,1))+CTABL(I,3);  ELSE PRINT"omn";
1900 NEXT I
1905 FOR I=25 TO 40:LOCATE CTABL(I,4),CTABL(I,5):JUNK=INT((PAR%(CTABL(I,1)))/12)-2:JUNK0=PAR%(CTABL(I,1))-((JUNK+2)*12):PRINT NOTES$(JUNK0);JUNK;:NEXT I
1910 FOR I=41 TO 64:LOCATE CTABL(I,4),CTABL(I,5):PRINT PAR%(CTABL(I,1))+CTABL(I,3);:NEXT I
1915 FOR I=65 TO 72:LOCATE CTABL(I,4),CTABL(I,5)
1920 IF PAR%(CTABL(I,1))=0 THEN PRINT"off";
1925 IF PAR%(CTABL(I,1))=1 THEN PRINT" I ";
1930 IF PAR%(CTABL(I,1))=2 THEN PRINT" II";
1935 IF PAR%(CTABL(I,1))=3 THEN PRINT"bth";
1940 NEXT I:FOR I=73 TO 80:LOCATE CTABL(I,4),CTABL(I,5)
1945 IF PAR%(CTABL(I,1))=0 THEN PRINT"off";
1950 IF PAR%(CTABL(I,1))=1 THEN PRINT" 1 ";
1955 IF PAR%(CTABL(I,1))=2 THEN PRINT" 2 ";
1960 IF PAR%(CTABL(I,1))=3 THEN PRINT"vib";
1965 NEXT I:FOR I=81 TO 88:LOCATE CTABL(I,4),CTABL(I,5)
1970 IF PAR%(CTABL(I,1))=0 THEN PRINT"off"; ELSE PRINT"on ";
1975 NEXT I
1980 LOCATE CTABL(89,4),CTABL(89,5):PRINT PAR%(CTABL(89,1))+CTABL(89,3);
1985 LOCATE CTABL(92,4),CTABL(92,5):PRINT NOTES$(PAR%(CTABL(89,1)));
1990 LOCATE CTABL(90,4),CTABL(90,5)
1995 IF PAR%(CTABL(90,1))=0 THEN PRINT"nrm"; ELSE PRINT"alt";
2000 LOCATE CTABL(91,4),CTABL(91,5):PRINT PAR%(CTABL(91,1));
2005 LOCATE 20,1:RETURN
2010 REM DISPLAY PERFORMANCE PARAMETERS ON CRT **
2015 PRINT:PRINT:OPEN "R",#1,PERFNAM$,122:LRN=CINT(LOF(1)/122)
2020 PRINT"enter performance record number for display ( 1 -";LRN;")";:INPUT CODE
2025 IF(CODE>0 AND CODE<=LRN)THEN GOTO 2030 ELSE PRINT"VALUE OUT OF RANGE":GOTO 2020
2030 FOR I%=1 TO 121:FIELD#1,(I%*1) AS OFFSET$,1 AS P$(I%):NEXT I%
2035 GET#1,CODE
2040 FOR I%=1 TO 121:PAR%(I%)=CVI(P$(I%)+NULL$):NEXT I%:CLOSE #1
2045 GOSUB 1790:REM draw table
2050 GOSUB 1840:REM fill in data
2055 PRINT:COLOR 15,1:PRINT"(any key to continue)";
2060 X$=INKEY$:IF(LEN(X$)=0)THEN 2060
2065 RETURN 190
2070 REM ADD PERFORMANCE TO current PerfLib *****
2075 OPEN "R",#1,PERFNAM$,122:FOR I%=1 TO 121:FIELD#1,(I%*1) AS OFFSET$,1 AS P$(I%):NEXT I%
2080 GOSUB 2180
2085 GOSUB 1580
2090 OUT STATPORT,255:OUT STATPORT,63
2095 GOSUB 1580
2100 PRINT:BEEP:PRINT"SELECT DESIRED PERFORMANCE ON TX/DX"
2105 IF INP(DATAPORT)<>240 GOTO 2105
2110 IF INP(DATAPORT)<>67 GOTO 2105
2115 IF INP(DATAPORT)<>CHAN% GOTO 2105
2120 IF INP(DATAPORT)<>126 GOTO 2105
2125 IF INP(DATAPORT)<>0 GOTO 2105
2130 IF INP(DATAPORT)<>120 GOTO 2105
2135 FOR I%=1 TO 121
2140 PAR%(I%)=INP(DATAPORT)
2145 NEXT I%
2150 IF INP(DATAPORT)=247 GOTO 2165
2155 PRINT"NO END OF DATA FROM SYNTH - RETURNING TO MAIN MENU"
2160 FOR I%=1 TO 500:NEXT I%:CLOSE #1:RETURN 190
2165 FOR I%=1 TO 121:RSET P$(I%)=MKI$(PAR%(I%)):NEXT I%
2170 PUT#1,LRN
2175 PRINT"Performance Dump Completed...Now ";LRN;" total performances in --> ";PERFNAM$ :CLOSE #1:RETURN 190
2180 REM subroutine to count number of records in current PERFLIB
2185 LRN=CINT(LOF(1)/122)+1
2190 RETURN
2195 REM WRITE A LIBRARY PERFORMANCE TO THE TX81Z ***
2200 PRINT:PRINT:OPEN "R",#1,PERFNAM$,122:FOR I%=1 TO 121:FIELD#1,(I%*1) AS OFFSET$,1 AS P$(I%):NEXT I%:LRN=CINT(LOF(1)/122)
2205 PRINT"enter record number of performance to write to TX81Z ( 1 -";LRN;")";:INPUT CODE
2210 IF(CODE>0 AND CODE<=LRN)THEN GOTO 2215 ELSE PRINT"VALUE OUT OF RANGE":GOTO 2205
2215 GET#1,CODE
2220 INPUT"select performance on TX81Z...press return when ready";RESP$
2225 FOR I%=1 TO 121:PAR%(I%)=CVI(P$(I%)+NULL$):NEXT I%:CLOSE #1
2230 GOSUB 1580
2235 OUT STATPORT,255
2240 OUT STATPORT,63
2245 FOR I%=1 TO 1000:JUNK%=INP(DATAPORT):NEXT I%
2250 OUT DATAPORT,240:OUT DATAPORT,67:OUT DATAPORT,CHAN%:OUT DATAPORT,126:OUT DATAPORT,0:OUT DATAPORT,120
2255 FOR I%=1 TO 121
2260 OUT DATAPORT,PAR%(I%)
2265 NEXT I%
2270 OUT DATAPORT,247
2275 IF WHERE=4 THEN RETURN
2280 GOSUB 805:REM set MX-8 to keyboard ==>> TX81Z
2285 PRINT "Performance ";:FOR I=111 TO 120:PRINT CHR$(PAR%(I));:NEXT I:PRINT" written to TX81Z":PRINT
2290 RETURN 190
2295 REM PATCH RANDOMIZER*****
2300 RANDOMIZE
2305 FOR I%=1 TO 128:PAR%(I%)=0:NEXT I%
2310 REM randomize patch variables
2315 FOR I=1 TO 97
2320 PAR%(PTABL(I,1))=INT(RND*(PTABL(I,2)+1))
2325 NEXT I
2330 PRINT"    enter random patch name";:INPUT FIL$
2335 FOR I=1 TO 10:JUNK(I)=32:NEXT I
2340 EXTENT=LEN(FIL$)
2345 IF(EXTENT>10)THEN EXTENT=10
2350 TEMP$=FIL$
2355 FOR I=EXTENT TO 1 STEP -1
2360 JUNK(I)=ASC(RIGHT$(TEMP$,1))
2365 TEMP$=LEFT$(TEMP$,(I-1))
2370 NEXT I
2375 FOR I=1 TO 10:PAR%(111+I)=JUNK(I):NEXT I
2380 GOSUB 1040:REM calculate checksum for PAR%(34) and PAR%(128)
2385 WHERE=1:GOSUB 1125
2390 GOSUB 1595:GOSUB 1660:LOCATE 23,1:COLOR 15,1:PRINT"store in library (y/n)?";
2395 RESP$=INKEY$:IF(LEN(RESP$)=0)THEN 2395
2400 IF(RESP$<>"n" AND RESP$<>"y")THEN GOTO 2395
2405 IF(RESP$="n"AND WHERE=5)THEN RETURN 1395
2410 IF(RESP$="n")THEN RETURN 190
2415 OPEN "R",#1,VOICNAM$,129:FOR I%=1 TO 128:FIELD#1,(I%*1) AS OFFSET$,1 AS P$(I%):NEXT I%
2420 GOSUB 1025
2425 FOR I%=1 TO 128:RSET P$(I%)=MKI$(PAR%(I%)):NEXT I%
2430 PUT#1,LRN
2435 PRINT"Patch Dump Completed...Now ";LRN;" patches in current PatchLib":CLOSE #1:IF(WHERE=1)THEN RETURN 190 ELSE RETURN 1395
2440 REM PATCH RANDOMIZER FROM SEED PATCH**
2445 PRINT:PRINT:OPEN "R",#1,VOICNAM$,129:FOR I%=1 TO 128:FIELD#1,(I%*1) AS OFFSET$,1 AS P$(I%):NEXT I%:LRN=CINT(LOF(1)/129)
2450 PRINT"enter seed patch record for randomization ( 1 -";LRN;")";:INPUT CODE
2455 IF(CODE>0 AND CODE<=LRN)THEN GOTO 2460 ELSE PRINT"VALUE OUT OF RANGE":GOTO 2450
2460 GET#1,CODE
2465 FOR I%=1 TO 128:PAR%(I%)=CVI(P$(I%)+NULL$):NEXT I%:CLOSE #1
2470 PRINT"Patch Name:";:FOR I%=112 TO 121:PRINT CHR$(PAR%(I%));:NEXT I%:PRINT
2475 INPUT"enter probability of changing any given parameter (0.00 - 1.00)";CHANGE
2480 IF(CHANGE<0! OR CHANGE>1!)THEN PRINT"VALUE OUT OF RANGE":GOTO 2475
2485 RANDOMIZE
2490 FOR I=1 TO 97
2495 IF(RND<CHANGE)THEN PAR%(PTABL(I,1))=INT(RND*(PTABL(I,2)+1))
2500 NEXT I
2505 PRINT"enter random patch name";:INPUT FIL$
2510 FOR I=1 TO 10:JUNK(I)=32:NEXT I
2515 EXTENT=LEN(FIL$)
2520 IF(EXTENT>10)THEN EXTENT=10
2525 TEMP$=FIL$
2530 FOR I=EXTENT TO 1 STEP -1
2535 JUNK(I)=ASC(RIGHT$(TEMP$,1))
2540 TEMP$=LEFT$(TEMP$,(I-1))
2545 NEXT I
2550 FOR I=1 TO 10:PAR%(111+I)=JUNK(I):NEXT I
2555 GOSUB 1040:REM calculate checksum for PAR%(34) and PAR%(128)
2560 WHERE=3:GOSUB 1125
2565 GOSUB 1595:GOSUB 1660:COLOR 15,1:LOCATE 23,1:PRINT"store in library (y/n)?";
2570 RESP$=INKEY$:IF(LEN(RESP$)=0)THEN 2570
2575 IF(RESP$="n")THEN RETURN 190
2580 OPEN "R",#1,VOICNAM$,129:FOR I%=1 TO 128:FIELD#1,(I%*1) AS OFFSET$,1 AS P$(I%):NEXT I%
2585 GOSUB 1025
2590 FOR I%=1 TO 128:RSET P$(I%)=MKI$(PAR%(I%)):NEXT I%
2595 PUT#1,LRN
2600 PRINT"Patch Dump Completed...Now ";LRN;" patches in current PatchLib":CLOSE #1:RETURN 190
2605 REM RANDOMIZE WITH TWO INPUT PATCHES FORMING PARAMETER BOUNDARIES
2610 PRINT:PRINT:OPEN "R",#1,VOICNAM$,129:FOR I%=1 TO 128:FIELD#1,(I%*1) AS OFFSET$,1 AS P$(I%):NEXT I%
2615 LRN=CINT(LOF(1)/129)
2620 PRINT"enter first patch record number for blend randomization ( 1 -";LRN;")";:INPUT CODE
2625 IF(CODE>0 AND CODE<=LRN)THEN GOTO 2630 ELSE PRINT"VALUE OUT OF RANGE":GOTO 2620
2630 GET#1,CODE
2635 FOR I%=1 TO 128:PARA%(I%)=CVI(P$(I%)+NULL$):NEXT I%
2640 PRINT"Patch Name:";
2645 FOR I%=112 TO 121:PRINT CHR$(PARA%(I%));:NEXT I%:PRINT
2650 PRINT"enter second patch record number for blend randomization ( 1 -";LRN;")";:INPUT CODE
2655 IF(CODE>0 AND CODE<=LRN)THEN GOTO 2660 ELSE PRINT"VALUE OUT OF RANGE":GOTO 2650
2660 GET#1,CODE
2665 FOR I%=1 TO 128:PARB%(I%)=CVI(P$(I%)+NULL$):NEXT I%:CLOSE #1
2670 PRINT"Patch Name:";
2675 FOR I%=112 TO 121:PRINT CHR$(PARB%(I%));:NEXT I%:PRINT
2680 RANDOMIZE
2685 FOR I=1 TO 128
2690 IF(PARA%(I)=PARB%(I))THEN PAR%(I)=PARA%(I)
2695 IF(PARA%(I)>PARB%(I))THEN GOSUB 2810
2700 IF(PARA%(I)<PARB%(I))THEN GOSUB 2825
2705 NEXT I
2710 PRINT"     enter new patch name";:INPUT FIL$
2715 FOR I=1 TO 10:JUNK(I)=32:NEXT I
2720 EXTENT=LEN(FIL$)
2725 IF(EXTENT>10)THEN EXTENT=10
2730 TEMP$=FIL$
2735 FOR I=EXTENT TO 1 STEP -1
2740 JUNK(I)=ASC(RIGHT$(TEMP$,1))
2745 TEMP$=LEFT$(TEMP$,(I-1))
2750 NEXT I
2755 FOR I=1 TO 10:PAR%(111+I)=JUNK(I):NEXT I
2760 GOSUB 1040:REM calculate checksum for PAR%(34) and PAR%(128)
2765 WHERE=2:GOSUB 1125
2770 GOSUB 1595:GOSUB 1660:COLOR 15,1:LOCATE 23,1:PRINT"store in library (y/n)?";
2775 RESP$=INKEY$:IF(LEN(RESP$)=0)THEN 2775
2780 IF(RESP$="n")THEN RETURN 190
2785 OPEN "R",#1,VOICNAM$,129:FOR I%=1 TO 128:FIELD#1,(I%*1) AS OFFSET$,1 AS P$(I%):NEXT I%
2790 GOSUB 1025
2795 FOR I%=1 TO 128:RSET P$(I%)=MKI$(PAR%(I%)):NEXT I%
2800 PUT#1,LRN
2805 PRINT"Patch Dump Completed...Now ";LRN;" patches in current PatchLib":CLOSE #1:RETURN 190
2810 REM para%(i) is ceiling, parb%(i) is floor
2815 PAR%(I)=PARB%(I)+INT(RND*(PARA%(I)-PARB%(I)))
2820 RETURN
2825 REM para%(i) is floor, parb%(i) is ceiling
2830 PAR%(I)=PARA%(I)+INT(RND*(PARB%(I)-PARA%(I)))
2835 RETURN
2840 REM patch editor
2845 PRINT:PRINT:OPEN "R",#1,VOICNAM$,129:FOR I%=1 TO 128:FIELD#1,(I%*1) AS OFFSET$,1 AS P$(I%):NEXT I%:LRN=CINT(LOF(1)/129)
2850 PRINT"enter seed patch record number for edit ( 1 -";LRN;")";:INPUT CODE
2855 IF(CODE>0 AND CODE<=LRN)THEN GOTO 2860 ELSE PRINT"VALUE OUT OF RANGE":GOTO 2850
2860 GET#1,CODE
2865 FOR I%=1 TO 128:PAR%(I%)=CVI(P$(I%)+NULL$):NEXT I%:CLOSE #1
2870 PRINT"Patch Name:";:FOR I%=112 TO 121:PRINT CHR$(PAR%(I%));:NEXT I%:PRINT
2875 GOSUB 3010
2880 FOR I%=1 TO 128:PARA%(I%)=PAR%(I%):NEXT I%
2885 GOSUB 1595:GOSUB 1660
2890 COLOR 14,1:LOCATE 17,50:PRINT "MENU";:LOCATE 18,40:PRINT"cursor keys: move cursor";:LOCATE 19,40:PRINT"s: start over    r: rename";:LOCATE 20,40:PRINT"l: listen        w: write to library";
2895 LOCATE 21,40:PRINT"c: change        n: new patch";:LOCATE 22,40:PRINT "q: quit";
2900 CRNT=1
2905 IF CRNT<1 THEN CRNT=97
2910 IF CRNT>97 THEN CRNT=1
2915 LOCATE PTABL(CRNT,4),PTABL(CRNT,5)-1:COLOR 30,1:PRINT">";
2920 RESP$=INKEY$:IF LEN(RESP$)=0 THEN 2920
2925 LOCATE PTABL(CRNT,4),PTABL(CRNT,5)-1:PRINT" ";
2930 IF ASC(RIGHT$(RESP$,1))=77 THEN CRNT=CRNT+1:GOTO 2905
2935 IF ASC(RIGHT$(RESP$,1))=75 THEN CRNT=CRNT-1:GOTO 2905
2940 IF ASC(RIGHT$(RESP$,1))=80 THEN GOSUB 3450:GOTO 2905
2945 IF ASC(RIGHT$(RESP$,1))=72 THEN GOSUB 3485:GOTO 2905
2950 IF RESP$="c" THEN GOSUB 3205:GOTO 2905
2955 IF ASC(RIGHT$(RESP$,1))=71 THEN CRNT=1:GOTO 2905
2960 IF ASC(RIGHT$(RESP$,1))=73 THEN CRNT=73:GOTO 2905
2965 IF ASC(RIGHT$(RESP$,1))=79 THEN CRNT=69:GOTO 2905
2970 IF ASC(RIGHT$(RESP$,1))=81 THEN CRNT=97:GOTO 2905
2975 IF RESP$="s" THEN FOR I%=1 TO 128:PAR%(I%)=PARA%(I%):NEXT I%:COLOR 15,1:GOTO 2885
2980 IF RESP$="q" THEN COLOR 15,1:CLS:RETURN
2985 IF RESP$="r" THEN COLOR 15,1:LOCATE 23,1:GOSUB 3010:LOCATE 23,1:PRINT SPC(40);:COLOR 1,3:LOCATE 1,7:FOR I=112 TO 121:PRINT CHR$(PAR%(I));:NEXT I:GOTO 2905
2990 IF RESP$="l" THEN LOCATE 23,1:COLOR 15,1:PRINT"Writing to TX81Z...please wait";:WHERE=4:GOSUB 785:GOSUB 1040:GOSUB 1125:GOSUB 805:LOCATE 23,1:PRINT SPC(30);:GOTO 2905
2995 IF RESP$="w" THEN GOSUB 1040:GOSUB 3070:GOTO 2905
3000 IF RESP$="n" THEN LOCATE 23,1:COLOR 15,1:GOSUB 3170
3005 GOTO 2915
3010 REM name patch
3015 PRINT:PRINT"enter new patch name";:INPUT FIL$
3020 FOR I=1 TO 10:JUNK(I)=32:NEXT I
3025 EXTENT=LEN(FIL$)
3030 IF(EXTENT>10)THEN EXTENT=10
3035 TEMP$=FIL$
3040 FOR I=EXTENT TO 1 STEP -1
3045 JUNK(I)=ASC(RIGHT$(TEMP$,1))
3050 TEMP$=LEFT$(TEMP$,(I-1))
3055 NEXT I
3060 FOR I=1 TO 10:PAR%(111+I)=JUNK(I):NEXT I
3065 RETURN
3070 REM write edited patch to library file
3075 OPEN "R",#1,VOICNAM$,129:FOR I%=1 TO 128:FIELD#1,(I%*1) AS OFFSET$,1 AS P$(I%):NEXT I%
3080 COLOR 15,1:LOCATE 23,1:PRINT"write patch at end or over old record (e/o)?";
3085 RESP$=INKEY$:IF LEN(RESP$)=0 THEN 3085
3090 IF(RESP$<>"e" AND RESP$<>"o")THEN 3085
3095 LOCATE 23,1:PRINT SPC(40);:LOCATE 23,1
3100 IF(RESP$="e")THEN LRN=CINT(LOF(1)/129)+1:GOTO 3145
3105 LRN=CINT(LOF(1)/129):PRINT"Enter patch number to write over ( 1 -";LRN;")";
3110 INPUT CODE:IF(CODE>0 AND CODE<=LRN)THEN 3115 ELSE LOCATE 23,1:PRINT SPC(40);:LOCATE 23,1:PRINT"VALUE OUT OF RANGE";:LOCATE 23,1:GOTO 3105
3115 GET #1,CODE:FOR I%=1 TO 128:PARB%(I%)=CVI(P$(I%)+NULL$):NEXT I%
3120 LOCATE 23,1:PRINT SPC(40);:LOCATE 23,1:PRINT"Old Patch:";:FOR I%=112 TO 121:PRINT CHR$(PARB%(I%));:NEXT I%:PRINT"...are you SURE you want to overwrite (y/n)?";
3125 RESP$=INKEY$:IF LEN(RESP$)=0 THEN 3125
3130 IF(RESP$<>"y" AND RESP$<>"n")THEN 3125
3135 IF RESP$="y" THEN LRN=CODE:LOCATE 23,1:PRINT SPC(70);:LOCATE 23,1:GOTO 3145
3140 LOCATE 23,1:PRINT SPC(70);:RETURN
3145 FOR I%=1 TO 128:RSET P$(I%)=MKI$(PAR%(I%)):NEXT I%
3150 PUT #1,LRN
3155 PRINT"Patch Dump Completed...Now ";CINT(LOF(1)/129);" patches in current PatchLib";:FOR I=1 TO 1000:NEXT I
3160 CLOSE #1:LOCATE 23,1:PRINT SPC(70);
3165 RETURN
3170 REM get new patch
3175 OPEN "R",#1,VOICNAM$,129:FOR I%=1 TO 128:FIELD#1,(I%*1) AS OFFSET$,1 AS P$(I%):NEXT I%:LRN=CINT(LOF(1)/129)
3180 PRINT"enter seed patch for edit ( 1 -";LRN;")";:INPUT CODE
3185 IF(CODE>0 AND CODE<=LRN)THEN GOTO 3190 ELSE LOCATE 23,1:PRINT SPC(50);:LOCATE 23,1:PRINT"VALUE OUT OF RANGE";:FOR I=1 TO 1000:NEXT I:LOCATE 23,1:PRINT SPC(40);:LOCATE 23,1:GOTO 3180
3190 LOCATE 23,1:PRINT SPC(50);
3195 GET#1,CODE:FOR I%=1 TO 128:PAR%(I%)=CVI(P$(I%)+NULL$):PARA%(I%)=PAR%(I%):NEXT I%:CLOSE #1
3200 GOSUB 1595:GOSUB 1660:RETURN 2890
3205 REM set new value
3210 LOCATE PTABL(CRNT,4),PTABL(CRNT,5)-1:COLOR 14,1:PRINT">";
3215 IF((CRNT>=5 AND CRNT<=8)OR(CRNT>=45 AND CRNT<=52)OR(CRNT>=61 AND CRNT<=64)OR(CRNT=75)OR(CRNT=76)OR(CRNT>=83 AND CRNT<=85))THEN GOTO 3245
3220 LOCATE 23,1:COLOR 15,1:PRINT"enter new parameter value (";PTABL(CRNT,3);"to";PTABL(CRNT,2)+PTABL(CRNT,3);")";:INPUT NVAL
3225 IF (NVAL<PTABL(CRNT,3) OR NVAL>(PTABL(CRNT,2)+PTABL(CRNT,3)))THEN LOCATE 23,1:PRINT SPC(60);:LOCATE 23,1:PRINT"VALUE OUT OF RANGE";:FOR I=1 TO 1000:NEXT I:LOCATE 23,1:PRINT SPC(60);:GOTO 3220
3230 LOCATE 23,1:PRINT SPC(79);
3235 PAR%(PTABL(CRNT,1))=NVAL-PTABL(CRNT,3):LOCATE PTABL(CRNT,4),PTABL(CRNT,5):COLOR 1,3:PRINT NVAL;
3240 RETURN
3245 REM exclusions for table changes
3250 LOCATE 23,1:COLOR 15,1
3255 IF(CRNT>=5 AND CRNT<=8)THEN GOTO 3315
3260 IF(CRNT>=45 AND CRNT<=48)THEN GOTO 3325
3265 IF(CRNT>=61 AND CRNT<=64)THEN GOTO 3340
3270 IF(CRNT=75)THEN GOTO 3350
3275 IF(CRNT=76)THEN GOTO 3340
3280 IF(CRNT=84)THEN GOTO 3390
3285 IF(CRNT=83)THEN GOTO 3305
3290 IF(CRNT>=49 AND CRNT<=52)THEN GOTO 3410
3295 IF(PAR%(PTABL(CRNT,1))=0)THEN PAR%(PTABL(CRNT,1))=1:R$="full" ELSE PAR%(PTABL(CRNT,1))=0:R$="off "
3300 LOCATE PTABL(CRNT,4),PTABL(CRNT,5):COLOR 1,3:PRINT R$;:RETURN
3305 IF(PAR%(PTABL(CRNT,1))=0)THEN PAR%(PTABL(CRNT,1))=1:R$="UNI" ELSE PAR%(PTABL(CRNT,1))=0:R$="PLY"
3310 LOCATE PTABL(CRNT,4),PTABL(CRNT,5):COLOR 1,3:PRINT R$;:RETURN
3315 IF(PAR%(PTABL(CRNT,1))=0)THEN PAR%(PTABL(CRNT,1))=1:R$="FXD" ELSE PAR%(PTABL(CRNT,1))=0:R$="RTO"
3320 LOCATE PTABL(CRNT,4),PTABL(CRNT,5):COLOR 1,3:PRINT R$;:RETURN
3325 PRINT"enter new parameter value (";PTABL(CRNT,3)+1;"to";PTABL(CRNT,2)+PTABL(CRNT,3);")";:INPUT NVAL
3330 IF (NVAL<PTABL(CRNT,3)+1 OR NVAL>(PTABL(CRNT,2)+PTABL(CRNT,3)))THEN LOCATE 23,1:PRINT SPC(60);:LOCATE 23,1:PRINT"VALUE OUT OF RANGE";:FOR I=1 TO 1000:NEXT I:LOCATE 23,1:PRINT SPC(60);:LOCATE 23,1:GOTO 3325
3335 GOTO 3230
3340 IF(PAR%(PTABL(CRNT,1))=0)THEN PAR%(PTABL(CRNT,1))=1:R$="on " ELSE PAR%(PTABL(CRNT,1))=0:R$="off"
3345 LOCATE PTABL(CRNT,4),PTABL(CRNT,5):COLOR 1,3:PRINT R$;:RETURN
3350 PRINT"enter new value (0=sin, 1=sqr, 2=tri, 3=s/h)";:INPUT NVAL
3355 IF(NVAL>=0 AND NVAL<=3)THEN GOTO 3360 ELSE LOCATE 23,1:PRINT SPC(60);:LOCATE 23,1:PRINT"VALUE OUT OF RANGE";:LOCATE 23,1:FOR I=1 TO 1000:NEXT I:PRINT SPC(60);:LOCATE 23,1:GOTO 3350
3360 PAR%(PTABL(CRNT,1))=NVAL:LOCATE 23,1:PRINT SPC(60);
3365 IF(NVAL=0)THEN R$="sin"
3370 IF(NVAL=1)THEN R$="sqr"
3375 IF(NVAL=2)THEN R$="tri"
3380 IF(NVAL=3)THEN R$="s/h"
3385 LOCATE PTABL(CRNT,4),PTABL(CRNT,5):COLOR 1,3:PRINT R$;:RETURN
3390 PRINT"enter new value (0-48: 0=C1, 12=C2, 24=C3, 36=C4, 48=C5)";:INPUT NVAL
3395 IF(NVAL>=0 AND NVAL<=48)THEN GOTO 3400 ELSE LOCATE 23,1:PRINT SPC(75);:LOCATE 23,1:PRINT"VALUE OUT OF RANGE";:LOCATE 23,1:FOR I=1 TO 1000:NEXT I:PRINT SPC(40);:LOCATE 23,1:GOTO 3390
3400 PAR%(PTABL(CRNT,1))=NVAL:LOCATE 23,1:PRINT SPC(75);:LOCATE PTABL(CRNT,4),PTABL(CRNT,5):COLOR 1,3
3405 GURN0=(PAR%(PTABL(84,1)))/12:GURN1=INT(GURN0):GURN2=CINT((GURN0-GURN1)*12):PRINT NOTES$(GURN2);GURN1+1;:RETURN
3410 PRINT"enter new value (0=off, 1=48dB, 2=24dB, 3=12dB)";:INPUT NVAL
3415 IF(NVAL>=0 AND NVAL<=3)THEN GOTO 3420 ELSE LOCATE 23,1:PRINT SPC(60);:LOCATE 23,1:PRINT"VALUE OUT OF RANGE";:LOCATE 23,1:FOR I=1 TO 1000:NEXT I:PRINT SPC(60);:LOCATE 23,1:GOTO 3410
3420 PAR%(PTABL(CRNT,1))=NVAL:LOCATE 23,1:PRINT SPC(60);
3425 IF(NVAL=0)THEN R$="off"
3430 IF(NVAL=1)THEN R$="48 "
3435 IF(NVAL=2)THEN R$="24 "
3440 IF(NVAL=3)THEN R$="12 "
3445 LOCATE PTABL(CRNT,4),PTABL(CRNT,5):COLOR 1,3:PRINT R$;:RETURN
3450 REM what to do with down arrow
3455 IF(CRNT>=1 AND CRNT<=68)THEN CRNT=CRNT+4:RETURN
3460 IF(CRNT>=69 AND CRNT<=72)THEN CRNT=73:RETURN
3465 IF(CRNT=73 OR CRNT=74)THEN CRNT=CRNT+1:RETURN
3470 IF(CRNT>=75 AND CRNT<=95)THEN CRNT=CRNT+2:RETURN
3475 IF(CRNT=97)THEN CRNT=1:RETURN
3480 IF(CRNT=96)THEN CRNT=97:RETURN
3485 REM what to do with up arrow
3490 IF(CRNT>=5 AND CRNT<=72)THEN CRNT=CRNT-4:RETURN
3495 IF(CRNT=73)THEN CRNT=69:RETURN
3500 IF(CRNT>=1 AND CRNT<=4)THEN CRNT=97:RETURN
3505 IF(CRNT=74)THEN CRNT=73:RETURN
3510 IF(CRNT=75 OR CRNT=76)THEN CRNT=74:RETURN
3515 IF(CRNT>=77 AND CRNT<=97)THEN CRNT=CRNT-2:RETURN
3520 REM performance editor
3525 PRINT:PRINT:OPEN "R",#1,PERFNAM$,122:FOR I%=1 TO 121:FIELD#1,(I%*1) AS OFFSET$,1 AS P$(I%):NEXT I%:LRN=CINT(LOF(1)/122)
3530 PRINT"enter seed performance record number for edit ( 1 -";LRN;")";:INPUT CODE
3535 IF(CODE>0 AND CODE<=LRN)THEN GOTO 3540 ELSE PRINT"VALUE OUT OF RANGE":GOTO 3530
3540 GET#1,CODE
3545 FOR I%=1 TO 121:PAR%(I%)=CVI(P$(I%)+NULL$):NEXT I%:CLOSE #1
3550 PRINT"Performance Name:";:FOR I%=111 TO 120:PRINT CHR$(PAR%(I%));:NEXT I%:PRINT
3555 GOSUB 3690
3560 FOR I%=1 TO 121:PARA%(I%)=PAR%(I%):NEXT I%
3565 GOSUB 1790:GOSUB 1840
3570 COLOR 14,1:LOCATE 17,50:PRINT "MENU";:LOCATE 18,40:PRINT"cursor keys: move cursor";:LOCATE 19,40:PRINT"s: start over    r: rename";:LOCATE 20,40:PRINT"l: listen        w: write to library";
3575 LOCATE 21,40:PRINT"c: change        n: new performance";:LOCATE 22,40:PRINT "q: quit";
3580 CRNT=1
3585 IF CRNT<1 THEN CRNT=92
3590 IF CRNT>92 THEN CRNT=1
3595 LOCATE CTABL(CRNT,4),CTABL(CRNT,5)-1:COLOR 30,1:PRINT">";
3600 RESP$=INKEY$:IF LEN(RESP$)=0 THEN 3600
3605 LOCATE CTABL(CRNT,4),CTABL(CRNT,5)-1:PRINT" ";
3610 IF ASC(RIGHT$(RESP$,1))=77 THEN GOSUB 4310:GOTO 3585
3615 IF ASC(RIGHT$(RESP$,1))=75 THEN GOSUB 4340:GOTO 3585
3620 IF ASC(RIGHT$(RESP$,1))=80 THEN GOSUB 4245:GOTO 3585
3625 IF ASC(RIGHT$(RESP$,1))=72 THEN GOSUB 4275:GOTO 3585
3630 IF RESP$="c" THEN GOSUB 3885:GOTO 3585
3635 IF ASC(RIGHT$(RESP$,1))=71 THEN CRNT=1:GOTO 3585
3640 IF ASC(RIGHT$(RESP$,1))=73 THEN CRNT=8:GOTO 3585
3645 IF ASC(RIGHT$(RESP$,1))=79 THEN CRNT=90:GOTO 3585
3650 IF ASC(RIGHT$(RESP$,1))=81 THEN CRNT=88:GOTO 3585
3655 IF RESP$="s" THEN FOR I%=1 TO 121:PAR%(I%)=PARA%(I%):NEXT I%:COLOR 15,1:GOTO 3565
3660 IF RESP$="q" THEN COLOR 15,1:CLS:RETURN
3665 IF RESP$="r" THEN COLOR 15,1:LOCATE 23,1:GOSUB 3690:LOCATE 23,1:PRINT SPC(40);:COLOR 1,3:LOCATE 1,7:FOR I=111 TO 120:PRINT CHR$(PAR%(I));:NEXT I:GOTO 3585
3670 IF RESP$="l" THEN LOCATE 23,1:COLOR 15,1:PRINT"Writing to TX81Z...please wait";:WHERE=4:GOSUB 785:GOSUB 4370:GOSUB 2230:GOSUB 805:LOCATE 23,1:PRINT SPC(30);:GOTO 3585
3675 IF RESP$="w" THEN GOSUB 4370:GOSUB 3750:GOTO 3585
3680 IF RESP$="n" THEN LOCATE 23,1:COLOR 15,1:GOSUB 3850
3685 GOTO 3595
3690 REM name performance
3695 PRINT:PRINT"enter new performance name";:INPUT FIL$
3700 FOR I=1 TO 10:JUNK(I)=32:NEXT I
3705 EXTENT=LEN(FIL$)
3710 IF(EXTENT>10)THEN EXTENT=10
3715 TEMP$=FIL$
3720 FOR I=EXTENT TO 1 STEP -1
3725 JUNK(I)=ASC(RIGHT$(TEMP$,1))
3730 TEMP$=LEFT$(TEMP$,(I-1))
3735 NEXT I
3740 FOR I=1 TO 10:PAR%(110+I)=JUNK(I):NEXT I
3745 RETURN
3750 REM write edited performance to library file
3755 OPEN "R",#1,PERFNAM$,122:FOR I%=1 TO 121:FIELD#1,(I%*1) AS OFFSET$,1 AS P$(I%):NEXT I%
3760 COLOR 15,1:LOCATE 23,1:PRINT"write performance at end or over old record (e/o)?";
3765 RESP$=INKEY$:IF LEN(RESP$)=0 THEN 3765
3770 IF(RESP$<>"e" AND RESP$<>"o")THEN 3765
3775 LOCATE 23,1:PRINT SPC(40);:LOCATE 23,1
3780 IF(RESP$="e")THEN LRN=CINT(LOF(1)/122)+1:GOTO 3825
3785 LRN=CINT(LOF(1)/122):PRINT"Enter performance number to write over ( 1 -";LRN;")";
3790 INPUT CODE:IF(CODE>0 AND CODE<=LRN)THEN 3795 ELSE LOCATE 23,1:PRINT SPC(40);:LOCATE 23,1:PRINT"VALUE OUT OF RANGE";:LOCATE 23,1:GOTO 3785
3795 GET #1,CODE:FOR I%=1 TO 121:PARB%(I%)=CVI(P$(I%)+NULL$):NEXT I%
3800 LOCATE 23,1:PRINT SPC(40);:LOCATE 23,1:PRINT"Old Performance:";:FOR I%=111 TO 120:PRINT CHR$(PARB%(I%));:NEXT I%:PRINT"...are you SURE you want to overwrite (y/n)?";
3805 RESP$=INKEY$:IF LEN(RESP$)=0 THEN 3805
3810 IF(RESP$<>"y" AND RESP$<>"n")THEN 3805
3815 IF RESP$="y" THEN LRN=CODE:LOCATE 23,1:PRINT SPC(70);:LOCATE 23,1:GOTO 3825
3820 LOCATE 23,1:PRINT SPC(70);:RETURN
3825 FOR I%=1 TO 121:RSET P$(I%)=MKI$(PAR%(I%)):NEXT I%
3830 PUT #1,LRN
3835 PRINT"Performance Dump Completed...Now ";CINT(LOF(1)/122);" total performances in-->" PERFNAM$;:FOR I=1 TO 1000:NEXT I
3840 CLOSE #1:LOCATE 23,1:PRINT SPC(70);
3845 RETURN
3850 REM get new performance
3855 OPEN "R",#1,PERFNAM$,122:FOR I%=1 TO 121:FIELD#1,(I%*1) AS OFFSET$,1 AS P$(I%):NEXT I%:LRN=CINT(LOF(1)/122)
3860 PRINT"enter seed performance for edit ( 1 -";LRN;")";:INPUT CODE
3865 IF(CODE>0 AND CODE<=LRN)THEN GOTO 3870 ELSE LOCATE 23,1:PRINT SPC(50);:LOCATE 23,1:PRINT"VALUE OUT OF RANGE";:FOR I=1 TO 1000:NEXT I:LOCATE 23,1:PRINT SPC(40);:LOCATE 23,1:GOTO 3860
3870 LOCATE 23,1:PRINT SPC(50);
3875 GET#1,CODE:FOR I%=1 TO 121:PAR%(I%)=CVI(P$(I%)+NULL$):PARA%(I%)=PAR%(I%):NEXT I%:CLOSE #1
3880 GOSUB 1790:GOSUB 1840:RETURN 3570
3885 REM set new value
3890 LOCATE CTABL(CRNT,4),CTABL(CRNT,5)-1:COLOR 14,1:PRINT">";
3895 IF((CRNT>=9 AND CRNT<=40)OR(CRNT>=65 AND CRNT<=88)OR(CRNT=90)OR(CRNT=92))THEN GOTO 3955
3900 LOCATE 23,1:COLOR 15,1:PRINT"enter new parameter value (";CTABL(CRNT,3);"to";CTABL(CRNT,2)+CTABL(CRNT,3);")";:INPUT NVAL
3905 IF (NVAL<CTABL(CRNT,3) OR NVAL>(CTABL(CRNT,2)+CTABL(CRNT,3)))THEN LOCATE 23,1:PRINT SPC(60);:LOCATE 23,1:PRINT"VALUE OUT OF RANGE";:FOR I=1 TO 1000:NEXT I:LOCATE 23,1:PRINT SPC(60);:GOTO 3900
3910 LOCATE 23,1:PRINT SPC(79);
3915 PAR%(CTABL(CRNT,1))=NVAL-CTABL(CRNT,3):LOCATE CTABL(CRNT,4),CTABL(CRNT,5):COLOR 1,3:PRINT NVAL;
3920 IF(CRNT>8)THEN GOTO 3930 ELSE JUNK=0:FOR I=1 TO 8:JUNK=PAR%(CTABL(I,1))+JUNK:NEXT I
3925 IF(JUNK<=8)THEN GOTO 3930 ELSE LOCATE 23,1:COLOR 1,4:PRINT"BEWARE - MORE THAN 8 NOTES ASSIGNED!!!";:LOCATE CTABL(CRNT,4),CTABL(CRNT,5):COLOR 1,3
3930 IF(CRNT<25 OR CRNT>32)THEN GOTO 3940 ELSE JUNK=PAR%(CTABL(CRNT,1)):JUNK0=PAR%(CTABL(CRNT+8,1))
3935 IF(JUNK<=JUNK0)THEN GOTO 3940 ELSE LOCATE 23,1:COLOR 1,4:PRINT"BEWARE - LOW LIMIT IS ABOVE HIGH LIMIT!!!";:LOCATE CTABL(CRNT,4),CTABL(CRNT,5):COLOR 1,3
3940 IF(CRNT<33 OR CRNT>40)THEN GOTO 3950 ELSE JUNK0=PAR%(CTABL(CRNT,1)):JUNK=PAR%(CTABL(CRNT-8,1))
3945 IF(JUNK<=JUNK0)THEN GOTO 3950 ELSE LOCATE 23,1:COLOR 1,4:PRINT"BEWARE - HIGH LIMIT IS BELOW LOW LIMIT LIMIT!!!";:LOCATE CTABL(CRNT,4),CTABL(CRNT,5):COLOR 1,3
3950 RETURN
3955 REM performance exceptions
3960 LOCATE 23,1:COLOR 15,1
3965 PRINT SPC(50);:LOCATE 23,1
3970 IF(CRNT>=9 AND CRNT<=16)THEN GOTO 4010
3975 IF(CRNT=90)THEN GOTO 4175
3980 IF(CRNT>=17 AND CRNT<=24)THEN GOTO 4160
3985 IF(CRNT=92)THEN GOTO 4185
3990 IF(CRNT>=65 AND CRNT<=72)THEN GOTO 4070
3995 IF(CRNT>=25 AND CRNT<=40)THEN GOTO 4210
4000 IF(CRNT>=73 AND CRNT<=80)THEN GOTO 4110
4005 IF(CRNT>=81 AND CRNT<=88)THEN GOTO 4150
4010 PRINT"enter patch bank of voice (a, b, c, d, or i)";:INPUT R$
4015 LOCATE 23,1:PRINT SPC(50);:IF(R$="a" OR R$="b" OR R$="c" OR R$="d" OR R$="i")THEN GOTO 4020 ELSE LOCATE 23,1:PRINT"VALUE OUT OF RANGE";:LOCATE 23,1:FOR I=1 TO 1000:NEXT I:PRINT SPC(40);:LOCATE 23,1:GOTO 4010
4020 IF R$="i" THEN X=0
4025 IF R$="a" THEN X=32
4030 IF R$="b" THEN X=64
4035 IF R$="c" THEN X=96
4040 IF R$="d" THEN X=128
4045 LOCATE 23,1:PRINT"enter patch number (1-32)";:INPUT NVAL:LOCATE 23,1:PRINT SPC(40);
4050 IF(NVAL>=1 AND NVAL<=32)THEN GOTO 4055 ELSE LOCATE 23,1:PRINT"VALUE OUT OF RANGE";:FOR I=1 TO 1000:NEXT I:LOCATE 23,1:PRINT SPC(40);:GOTO 4045
4055 LOCATE CTABL(CRNT,4),CTABL(CRNT,5):COLOR 1,3:PRINT R$;NVAL;:NVAL=NVAL+X-1
4060 IF(NVAL>=128)THEN PAR%(CTABL(CRNT,1))=1:PAR%(CTABL(CRNT,1)+1)=NVAL-128 ELSE PAR%(CTABL(CRNT,1))=0:PAR%(CTABL(CRNT,1)+1)=NVAL
4065 RETURN
4070 PRINT"enter output assignment (0=off, 1=I, 2=II, 3=I+II)";:INPUT NVAL
4075 LOCATE 23,1:PRINT SPC(50);:IF(NVAL>=0 AND NVAL<=3)THEN GOTO 4080 ELSE PRINT"VALUE OUT OF RANGE";:FOR I=1 TO 1000:NEXT I:LOCATE 23,1:PRINT SPC(40);:LOCATE 23,1:GOTO 4070
4080 PAR%(CTABL(CRNT,1))=NVAL:LOCATE CTABL(CRNT,4),CTABL(CRNT,5):COLOR 1,3
4085 IF NVAL=0 THEN PRINT"off";
4090 IF NVAL=1 THEN PRINT" I ";
4095 IF NVAL=2 THEN PRINT" II";
4100 IF NVAL=3 THEN PRINT"bth";
4105 RETURN
4110 PRINT"enter LFO assignment (0=off, 1=1, 2=2, 3=vib)";:INPUT NVAL
4115 LOCATE 23,1:PRINT SPC(60);:IF(NVAL>=0 AND NVAL<=3)THEN GOTO 4120 ELSE PRINT"VALUE OUT OF RANGE";:FOR I=1 TO 1000:NEXT I:LOCATE 23,1:PRINT SPC(40);:LOCATE 23,1:GOTO 4110
4120 PAR%(CTABL(CRNT,1))=NVAL:LOCATE CTABL(CRNT,4),CTABL(CRNT,5):COLOR 1,3
4125 IF NVAL=0 THEN PRINT"off";
4130 IF NVAL=1 THEN PRINT" 1 ";
4135 IF NVAL=2 THEN PRINT" 2 ";
4140 IF NVAL=3 THEN PRINT"vib";
4145 RETURN
4150 IF(PAR%(CTABL(CRNT,1))=0)THEN R$="on ":PAR%(CTABL(CRNT,1))=1 ELSE R$="off":PAR%(CTABL(CRNT,1))=0
4155 LOCATE CTABL(CRNT,4),CTABL(CRNT,5):COLOR 1,3:PRINT R$;:RETURN
4160 PRINT"enter MIDI channel (1-16, 17=omni)";:INPUT NVAL
4165 IF(NVAL>=1 AND NVAL<=17)THEN GOTO 4170 ELSE LOCATE 23,1:PRINT SPC(40);:LOCATE 23,1:PRINT"VALUE OUT OF RANGE";:LOCATE 23,1:FOR I=1 TO 1000:NEXT I:PRINT SPC(40);:LOCATE 23,1:GOTO 4160
4170 LOCATE 23,1:PRINT SPC(40);:COLOR 1,3:LOCATE CTABL(CRNT,4),CTABL(CRNT,5):IF(NVAL<17)THEN PRINT NVAL;:RETURN ELSE PRINT"omn";:RETURN
4175 IF(PAR%(CTABL(CRNT,1))=0)THEN R$="alt":PAR%(CTABL(CRNT,1))=1 ELSE R$="nrm":PAR%(CTABL(CRNT,1))=0
4180 LOCATE CTABL(CRNT,4),CTABL(CRNT,5):COLOR 1,3:PRINT R$;:RETURN
4185 PRINT"enter new key (0-11: 0=c, 1=c#...11=b)";:INPUT NVAL
4190 LOCATE 23,1:PRINT SPC(60);:IF(NVAL>=0 AND NVAL<=11)THEN GOTO 4195 ELSE PRINT"VALUE OUT OF RANGE";:FOR I=1 TO 1000:NEXT I:LOCATE 23,1:PRINT SPC(40);:LOCATE 23,1:GOTO 4185
4195 PAR%(CTABL(CRNT,1))=NVAL:LOCATE CTABL(CRNT,4),CTABL(CRNT,5):COLOR 1,3
4200 PRINT NOTES$(NVAL);:RETURN
4205 RETURN:REM micro-key change
4210 LOCATE 23,1:COLOR 15,1:PRINT"enter note value (1=c, 2=c#...12=b)";:INPUT NVAL
4215 IF (NVAL<1 OR NVAL>12)THEN LOCATE 23,1:PRINT SPC(60);:LOCATE 23,1:PRINT"VALUE OUT OF RANGE";:FOR I=1 TO 1000:NEXT I:LOCATE 23,1:PRINT SPC(60);:GOTO 4210
4220 LOCATE 23,1:PRINT SPC(60);:LOCATE 23,1:PRINT"enter octave value (-2 to 8)";:INPUT NVAL2
4225 IF (NVAL2<-2 OR NVAL2>8)THEN LOCATE 23,1:PRINT SPC(60);:LOCATE 23,1:PRINT"VALUE OUT OF RANGE";:FOR I=1 TO 1000:NEXT I:LOCATE 23,1:PRINT SPC(60);:GOTO 4220
4230 LOCATE 23,1:PRINT SPC(60);:TEMP=NVAL+((NVAL2+2)*12):IF(TEMP<1)THEN TEMP=1:NVAL=1
4235 IF(TEMP>128)THEN TEMP=128:NVAL=8:NVAL2=8
4240 PAR%(CTABL(CRNT,1))=TEMP:LOCATE CTABL(CRNT,4),CTABL(CRNT,5):COLOR 1,3:PRINT NOTES$(NVAL-1);NVAL2;:GOTO 3930
4245 REM what to do with down arrow
4250 IF(CRNT>=1 AND CRNT<=80)THEN CRNT=CRNT+8:RETURN
4255 IF(CRNT>=81 AND CRNT<=88)THEN CRNT=89:RETURN
4260 IF(CRNT=89)THEN CRNT=90:RETURN
4265 IF(CRNT=90 OR CRNT=91)THEN CRNT=1:RETURN
4270 IF(CRNT=92)THEN CRNT=91:RETURN
4275 REM what to do with up arrow
4280 IF(CRNT>=9 AND CRNT<=88)THEN CRNT=CRNT-8:RETURN
4285 IF(CRNT>=1 AND CRNT<=8)THEN CRNT=90:RETURN
4290 IF(CRNT=89)THEN CRNT=81:RETURN
4295 IF(CRNT=90)THEN CRNT=89:RETURN
4300 IF(CRNT=91)THEN CRNT=92:RETURN
4305 IF(CRNT=92)THEN CRNT=81:RETURN
4310 REM what to do with right arrow
4315 IF(CRNT>=1 AND CRNT<=88)THEN CRNT=CRNT+1:RETURN
4320 IF(CRNT=89)THEN CRNT=92:RETURN
4325 IF(CRNT=90)THEN CRNT=91:RETURN
4330 IF(CRNT=91)THEN CRNT=1:RETURN
4335 IF(CRNT=92)THEN CRNT=90:RETURN
4340 REM what to do with left arrow
4345 IF(CRNT>=2 AND CRNT<=89)THEN CRNT=CRNT-1:RETURN
4350 IF(CRNT=1)THEN CRNT=91:RETURN
4355 IF(CRNT=90)THEN CRNT=92:RETURN
4360 IF(CRNT=91)THEN CRNT=90:RETURN
4365 IF(CRNT=92)THEN CRNT=89:RETURN
4370 REM calculate two's-compliment checksum for altered performance records
4375 CHSUM=0:FOR I=1 TO 120:CHSUM=CHSUM+PAR%(I):NEXT I
4380 CHSUM=128*((CHSUM/128)-(INT(CHSUM/128))):CHSUM=128-CHSUM:PAR%(121)=CHSUM
4385 :
4390 REM *******
4395 REM ....... SET NEW VOICE LIB FILENAME
4400 INPUT "desired patch lib file (xxx.pat) : ";A$
4405 OPEN "I",#1,A$ : CLOSE #1
4410 VOICNAM$ = A$
4415 RETURN
4420 :
4425 REM  ......SET NEW PERF LIB FILENAME
4430 INPUT "desired Perf lib file (xxx.cmb) : ";A$
4435 OPEN "I",#1,A$  : CLOSE #1
4440 PERFNAM$ = A$
4445 RETURN
4450 :
4455 REM ......set midi channel ...default= 1.........
4460 PRINT: INPUT "Enter desired midi chan <1-16>:  ";CHAN%
4465 IF CHAN% > 16  THEN    CHAN% = 1
4470 CHAN% = CHAN% -1 : RETURN
4475 :
4480 CLS:  COLOR 15,3:PRINT"  ***** PLAY NOTES ON TX81Z using keyboard *****"
4485 COLOR 15,1
4490  FOR I%=1 TO 300:JUNK%=INP(DATAPORT):NEXT I%
4495 OUT STATPORT,255 : OUT STATPORT,63
4500 BY1=144+CHAN%
4505 PRINT"USE KEYS    C - D - E - F - G - A - B   TO PLAY NOTES": PRINT
4510 PRINT"   '+' octave up      '-' octave down"
4515 PRINT"   '[' velocity-10   ']'  velocity+10"
4520 PRINT"   '{' length-10     '}' length+10    ( 160 =~ 1sec??)"
4525 PRINT:PRINT"hit 'q'to quit."
4530 LOCATE 15,1:    PRINT"octave: " NOTEOCT
4535 LOCATE 17,1:    PRINT"velocity" NOTEVEL
4540 LOCATE 19,1:    PRINT"length: " NOTELEN
4545 RESP$=INKEY$:IF LEN(RESP$)<>0 THEN 4555
4550 FOR I=0 TO 10 : JUNK%=INP(DATAPORT):NEXT I :GOTO 4545
4555 IF NOTEOCT>1  AND  RESP$="-" THEN NOTEOCT = NOTEOCT -1:GOTO 4530
4560 IF NOTEOCT<6  AND  RESP$="+" THEN NOTEOCT = NOTEOCT +1:GOTO 4530
4565 IF NOTEVEL>10  AND  RESP$="[" THEN NOTEVEL = NOTEVEL -10:GOTO 4530
4570 IF NOTEVEL<120 AND  RESP$="]" THEN NOTEVEL = NOTEVEL +10:GOTO 4530
4575 IF NOTELEN>10 AND  RESP$="{" THEN NOTELEN = NOTELEN-10:GOTO 4530
4580 IF NOTELEN<5000 AND  RESP$="}" THEN NOTELEN = NOTELEN+10 :GOTO 4530
4585 IF RESP$ ="c" THEN   BY2 = 36+12*(NOTEOCT-1) :GOTO 4630
4590 IF RESP$ ="d" THEN   BY2 = 38+12*(NOTEOCT-1) :GOTO 4630
4595 IF RESP$ ="e" THEN   BY2 = 40+12*(NOTEOCT-1) :GOTO 4630
4600 IF RESP$ ="f" THEN   BY2 = 41+12*(NOTEOCT-1) :GOTO 4630
4605 IF RESP$ ="g" THEN   BY2 = 43+12*(NOTEOCT-1) :GOTO 4630
4610 IF RESP$ ="a" THEN   BY2 = 45+12*(NOTEOCT-1) :GOTO 4630
4615 IF RESP$ ="b" THEN   BY2 = 47+12*(NOTEOCT-1) :GOTO 4630
4620 IF RESP$="q" GOTO 4655
4625 GOTO 4545
4630 LAST$=RESP$ : LOCATE 13,1: PRINT"last note: "LAST$
4635 OUT DATAPORT,BY1 : OUT DATAPORT,BY2 : OUT DATAPORT,NOTEVEL: REM ..note-on,key#,velocity
4640 FOR I=1 TO NOTELEN: NEXT I
4645 OUT DATAPORT,BY1 : OUT DATAPORT,BY2: OUT DATAPORT,0 : REM ..note-off..
4650 GOTO 4530
4655 GOSUB 4955:OUT STATPORT,255: OUT STATPORT,63: GOSUB 4955: RETURN
4660 :
4665 PRINT"....SEND PATCH CHANGE........"
4670 PRINT"note: default- perf patch changes are not in TX81Z prog chg table.."
4675 OUT STATPORT,255: OUT STATPORT,63: CLS:
4680 GOSUB 4955 : REM ..clear input port
4685 INPUT"Enter bank [a,b,c,d,i,perf]";A$
4690 IF A$<>"a" AND A$<>"b"AND A$<>"c"AND A$<>"d"AND A$<>"i"AND A$<>"perf" THEN GOTO 4665
4695 CLS: PRINT"BANK:  "A$
4700 INPUT"Enter patch# [1-32]";PATNUM
4705 IF PATNUM<1 OR PATNUM>32 THEN GOTO 4695
4710 IF A$="i" THEN PAT=PATNUM-1:PRESS=112
4715 IF A$="a" THEN PAT=PATNUM+31:PRESS=108
4720 IF A$="b" THEN PAT=PATNUM+63:PRESS=109
4725 IF A$="c" THEN PAT=PATNUM+95:PRESS=110
4730 IF A$="d" THEN PAT=PATNUM+127:PRESS=111
4735 IF A$="perf" THEN PAT=PATNUM+159:PRESS=119
4740 IF TXSEL=1 THEN 4760
4745 STATE=127:BUTTON=118:GOSUB 4815:STATE=0:GOSUB 4815:GOSUB 4955
4750 STATE=127:BUTTON=PRESS:GOSUB 4815:BUTTON=75+PATNUM:GOSUB 4815:GOSUB 4955
4755 STATE=0:GOSUB 4815:RETURN
4760 OUT DATAPORT,192+CHAN%: OUT DATAPORT,PAT
4765 PRINT:PRINT:PRINT"Patch code sent: "PAT
4770 FOR I=1 TO 1000: NEXT I
4775 OUT STATPORT,255: OUT STATPORT,63: RETURN
4780 :
4785 REM .. PRESS data entry '+' BUTTON ON TX81Z VIA MIDI
4790 BUTTON= 72: STATE= 127: GOSUB 4815 : RETURN
4795 :
4800 REM .. PRESS data entry '-' BUTTON ON TX81Z VIA MIDI
4805 BUTTON= 71: STATE= 127: GOSUB 4815 : RETURN
4810 :
4815 REM .... put TX81Z   "BUTTON" specfied  in "STATE" specified
4820 REM Tx buttons are remote switch params. STATE has values 0 (off) or 127(on)
4825 OUT STATPORT,255: OUT STATPORT,63: GOSUB 4955
4830 OUT DATAPORT,240:OUT DATAPORT,67: OUT DATAPORT,16+CHAN%  : REM sysex start
4835 OUT DATAPORT,19 : REM ..group/subgroup
4840 OUT DATAPORT,BUTTON : OUT DATAPORT,STATE : REM ..param# - data
4845 OUT DATAPORT,247 : REM .. end of sysex
4850 RETURN
4855 :
4860 REM ..SWITCH MEM PROTECT OFF.....
4865 IF TXSEL=1 THEN   MEMBUT=71 :GOSUB 4910: RETURN
4870 BUTTON=116:STATE=127 :GOSUB 4815:BUTTON=122:GOSUB 4815:BUTTON=118:GOSUB 4815
4875 RETURN : REM ... for DX only
4880 :
4885 REM ..SWITCH MEM PROTECT ON.....
4890 IF TXSEL=1 THEN   MEMBUT=72 :GOSUB 4910 : RETURN
4895 BUTTON=116:STATE=127 :GOSUB 4815:BUTTON = 123:GOSUB 4815:BUTTON=118:GOSUB 4815
4900 RETURN : REM ... for DX only
4905 :
4910 REM FINISH MEM PROTECT OFF/ON sequence . for TX81z only......
4915 STATE=127
4920 BUTTON=66 : GOSUB 4815:  REM -press util button
4925 BUTTON=69 : FOR IB=1 TO 10 : GOSUB 4815: NEXT IB :REM - 10 presses of param-1 button
4930 BUTTON=70 : FOR IB=1 TO 2 :  GOSUB 4815: NEXT IB :REM -press 2 presses of param+1 button
4935 BUTTON=MEMBUT : GOSUB 4815: REM -press data entry -1 or +1  button
4940 BUTTON=68 : GOSUB 4815:  REM -press PLAY button
4945 RETURN
4950 :
4955 REM clear read port
4960 FOR I%=1 TO 300 :JUNK%=INP(DATAPORT):NEXT I%
4965 RETURN
4970 :
4975 PRINT"***** READ 'I' BANK (from TX/DX) into  'tempfile'  ******"
4980 PRINT" 'c' to continue,  'a' to abort..."
4985 RESP$=INKEY$: IF RESP$<>"a" AND RESP$<>"c" THEN 4985
4990 IF RESP$="a" THEN RETURN
4995 OPEN "R",#1,"tempfile",129:CLOSE #1 : KILL "tempfile"
5000 PRINT"please wait...reading 32 patches from bank 'I' into 'tempfile'"
5005 IF TXSEL=1 THEN 5020
5010 STATE=127:BUTTON=118:GOSUB 4815:STATE=0:GOSUB 4815:STATE=127:BUTTON=112
5015 GOSUB 4815:STATE=0:GOSUB 4815:OUT STATPORT,255:OUT STATPORT,63:GOSUB 4955
5020 GOSUB 4955 : OUT STATPORT,255 : OUT STATPORT,63: GOSUB 4955
5025 DXPAT1=76: STATE=127: REM dx's patch#1 button
5030 IF TXSEL=1 THEN   OUT DATAPORT,192+CHAN% : OUT DATAPORT,1    : REM ..patch 'I02' on TX81Z
5035 FOR PP=1 TO 32 	:REM ..patch read loop starts here
5040 A$=INKEY$: IF LEN(A$)<>0 THEN  RETURN :REM abort...
5045 OPEN "R",#1,"tempfile",129:FOR I%=1 TO 128:FIELD#1,(I%*1) AS OFFSET$,1 AS P$(I%):NEXT I% :GOSUB 1025
5050 PRINT PP" ";
5055 IF TXSEL=1 THEN GOTO 5070
5060 STATE=127:BUTTON=DXPAT1:GOSUB 4815:DXPAT1=DXPAT1+1:REM press a DX patch buttons
5065 GOTO 5095
5070 REM ...TX handler
5075 IF PP=1 THEN GOSUB 4800: REM .."push" data- button (to get patch 'I01' )
5080 IF PP>1 THEN GOSUB 4785: REM .. ELSE, push data+ button...
5085 REM .. when patch is selected, TX/DX sends voice data
5090 REM ...Now, read the patch from synth. ACED & SCED
5095 ERRCT=0 : FIRST=0 :TIMEOUT=0
5100 IF ERRCT = 7000 AND FIRST =0 THEN BEEP: RETURN
5105 IF ERRCT = 3000 THEN PRINT"ERROR! ABORTING. CHECK: TX81z sysex on, cables , etc.."
5110 IF INP(DATAPORT)<>240  THEN ERRCT = ERRCT +1 : GOTO 5100
5115 FIRST =1
5120 IF INP(DATAPORT)<>67 GOTO 5110
5125 IF INP(DATAPORT)<>CHAN% GOTO 5110
5130 IF INP(DATAPORT)<>126 GOTO 5110
5135 IF INP(DATAPORT)<>0 GOTO 5110
5140 IF INP(DATAPORT)<>33 GOTO 5110
5145 FOR I%=1 TO 34: PAR%(I%)=INP(DATAPORT) : NEXT I%
5150 IF INP(DATAPORT)<>247 GOTO 5110
5155 IF INP(DATAPORT)<>240 GOTO 5155
5160 IF INP(DATAPORT)<>67 GOTO 5155
5165 IF INP(DATAPORT)<>CHAN% GOTO 5155
5170 IF INP(DATAPORT)<>3 GOTO 5155
5175 IF INP(DATAPORT)<>0 GOTO 5155
5180 IF INP(DATAPORT)<>93 GOTO 5155
5185 FOR I%=35 TO 128 : PAR%(I%)=INP(DATAPORT) : NEXT I%
5190 IF INP(DATAPORT)=247 GOTO 5205
5195 PRINT"NO END OF DATA FROM SYNTH - RETURNING TO MAIN MENU"
5200 FOR I%=1 TO 500:NEXT I%:CLOSE #1:RETURN 190
5205 FOR I%=1 TO 128:RSET P$(I%)=MKI$(PAR%(I%)):NEXT I%
5210 PUT#1,LRN
5215 CLOSE #1
5220 FOR I%=112 TO 121:PRINT CHR$(PAR%(I%));:NEXT I%:PRINT
5225 BEEP: NEXT PP: REM ... patch read loop ENDS here......
5230 FOR I%=1 TO 500 : NEXT I%
5235 RETURN
5240 :
5245 PRINT"  ****  WRITE GROUP of PATCHES TO TX/DX  'I' BANK *****"
5250 WHERE=0
5255 OPEN "R",#1,VOICNAM$,129:FOR I%=1 TO 128:FIELD#1,(I%*1) AS OFFSET$,1 AS P$(I%):NEXT I%
5260 LRN=CINT(LOF(1)/129): CLOSE #1
5265 PRINT"enter starting lib file patch record number (1 -";LRN;")";:INPUT CODE
5270 IF(CODE>0 AND CODE <=LRN)THEN GOTO 5275 ELSE PRINT"VALUE OUT OF RANGE- ABORTING!":FOR I=1 TO 2000 : NEXT I: RETURN
5275 REM ....patch write loop begins here....
5280 CNT=0:PRINT
5285 FOR PP=CODE TO CODE+31 :CNT=CNT+1: PRINT CODE+CNT-1" ";
5290 A$=INKEY$: IF LEN(A$)<>0 THEN RETURN :REM abort...
5295 OPEN "R",#1,VOICNAM$,129:FOR I%=1 TO 128:FIELD#1,(I%*1) AS OFFSET$,1 AS P$(I%):NEXT I%
5300 GET #1,PP
5305 FOR I%=1 TO 128:PAR%(I%)=CVI(P$(I%)+NULL$):NEXT I%
5310 IF TXSEL=1 THEN 5320
5315 GOTO 5325
5320 OUT DATAPORT,192+CHAN%: OUT DATAPORT,CNT-1: REM ..'I' bank patch change
5325 GOSUB 4955
5330 OUT STATPORT,255 : OUT STATPORT,63
5335 GOSUB 4955
5340 OUT DATAPORT,240:OUT DATAPORT,67:OUT DATAPORT,CHAN%:OUT DATAPORT,126:OUT DATAPORT,0:OUT DATAPORT,33
5345 FOR I%=1 TO 34:OUT DATAPORT,PAR%(I%):NEXT I%:OUT DATAPORT,247
5350 OUT DATAPORT,240:OUT DATAPORT,67:OUT DATAPORT,CHAN%:OUT DATAPORT,3:OUT DATAPORT,0:OUT DATAPORT,93
5355 FOR I%=35 TO 128:OUT DATAPORT,PAR%(I%):NEXT I%:OUT DATAPORT,247
5360 CLOSE#1
5365 FOR I%=112 TO 121:PRINT CHR$(PAR%(I%));:NEXT I%:PRINT
5370 GOSUB 5765: REM ...do "TX/DX permanent mem store seq"..........
5375 NEXT PP:	REM ..patch write loop ends here...
5380 RETURN
5385 :
5390 REM ...Save user setup to file
5395 ON ERROR GOTO 5405
5400 KILL "user.def" : GOTO 5410
5405 RESUME NEXT
5410 OPEN "user.def" FOR OUTPUT AS #1
5415 PRINT#1,CHAN% : PRINT#1,VOICNAM$ : PRINT#1,PERFNAM$
5420 PRINT#1,NOTEOCT : PRINT#1,NOTELEN : PRINT#1,NOTEVEL: PRINT#1,TXSEL
5425 CLOSE#1 : RETURN
5430 :
5435 REM ....Read user setup from file
5440 ON ERROR GOTO 5465 : REM ..handles case where default file not present..
5445 OPEN "user.def" FOR INPUT AS #1
5450 INPUT#1,CHAN%: INPUT#1,VOICNAM$: INPUT#1,PERFNAM$
5455 INPUT#1,NOTEOCT : INPUT#1,NOTELEN : INPUT#1,NOTEVEL:INPUT#1,TXSEL
5460 CLOSE#1 : GOTO 5470
5465 RESUME 150:
5470 RETURN
5475 :
5480 CLS: PRINT"********* DIRECTORY *********"
5485 FILES : PRINT"< hit any key >"
5490 X$=INKEY$:IF(LEN(X$)=0)THEN 5490
5495 RETURN
5500 :
5505 REM Subroutine lists a range of patches in given patchlib
5510 REM Expects name of patch lib to be in string variable --> VOICE$
5515 PRINT:PRINT"PATCH FILES IN: ";VOICE$
5520 PRINT "to (s)creen-only  or  (p)rinter & screen ?"
5525 STDOUT$=INKEY$: IF LEN(STDOUT$)=0 THEN GOTO 5525
5530 OPEN "R",#1,VOICE$,129:RN=1
5535 FOR I%=1 TO 128:FIELD#1,(I%*1) AS OFFSET$,1 AS P$(I%):NEXT I%
5540 LRN=CINT(LOF(1)/129):PRINT"Total Patches:";LRN:PRINT
5545 PRINT:INPUT"Enter STARTing patch number:";SPTCH: INPUT"Enter ENDing patch number:";EPTCH:IF(EPTCH<SPTCH OR SPTCH<1 OR EPTCH >LRN)THEN PRINT"entry error...":BEEP:RETURN
5550 LRN=EPTCH
5555 RLIM=1+INT((LRN-SPTCH+1)/4)
5560 FOR RN=1 TO RLIM
5565 FOR CLM=1 TO 4
5570 IF(SPTCH-1+RN+((CLM-1)*RLIM))>LRN THEN GOTO 5600  ELSE GET#1,SPTCH-1+RN+((CLM-1)*RLIM)
5575 FOR I%=1 TO 128:PAR%(I%)=CVI(P$(I%)+NULL$):NEXT I%
5580 PRINT USING"####";SPTCH-1+RN+((CLM-1)*RLIM);:PRINT": ";
5585 IF(STDOUT$="p") THEN LPRINT USING"####";SPTCH-1+RN+((CLM-1)*RLIM);:LPRINT": ";
5590 FOR I%=112 TO 121:PRINT CHR$(PAR%(I%));:NEXT I%:PRINT"    ";
5595 IF(STDOUT$="p") THEN FOR I%=112 TO 121:LPRINT CHR$(PAR%(I%));:NEXT I%:LPRINT"    ";
5600 NEXT CLM:
5605 A$=INKEY$: IF LEN(A$) <> 0 THEN GOTO 5615
5610 NEXT RN
5615 CLOSE #1
5620 STDOUT$=" ":PRINT" < hit any key >":PRINT
5625 A$=INKEY$: IF LEN(A$)=0 THEN GOTO 5625
5630 RETURN
5635 :
5640 REM WRITE A (current) LIBRARY PATCH TO TX's  'I' bank *********
5645 WHERE=0
5650 OPEN "R",#1,VOICNAM$,129:FOR I%=1 TO 128:FIELD#1,(I%*1) AS OFFSET$,1 AS P$(I%):NEXT I%
5655 LRN=CINT(LOF(1)/129)
5660 PRINT"enter library patch number to write to TX/DX (1 -";LRN;")";:INPUT CODE
5665 IF(CODE>0 AND CODE <=LRN)THEN GET #1,CODE ELSE PRINT"VALUE OUT OF RANGE":BEEP:GOTO 1185
5670 :
5675 INPUT"Enter TX/DX Ibank patch# [1-32] to receive this lib patch: ";TRP :
5680 IF TRP <1 OR TRP >32 THEN TRP=CODE
5685 IF TXSEL=0 THEN 5695
5690 OUT DATAPORT,192+CHAN%: OUT DATAPORT,TRP-1: REM .. send patch change
5695 GOSUB 4955 : OUT STATPORT,255 : OUT STATPORT,63: GOSUB 4955
5700 :
5705 FOR I%=1 TO 128:PAR%(I%)=CVI(P$(I%)+NULL$):NEXT I%
5710 GOSUB 1580 : REM flush midi port
5715 OUT STATPORT,255: OUT STATPORT,63
5720 REM FOR I%=1 TO 1000:JUNK%=INP(DATAPORT):NEXT I%
5725 OUT DATAPORT,240:OUT DATAPORT,67:OUT DATAPORT,CHAN%:OUT DATAPORT,126:OUT DATAPORT,0:OUT DATAPORT,33
5730 FOR I%=1 TO 34:OUT DATAPORT,PAR%(I%):NEXT I%:OUT DATAPORT,247
5735 OUT DATAPORT,240:OUT DATAPORT,67:OUT DATAPORT,CHAN%:OUT DATAPORT,3:OUT DATAPORT,0:OUT DATAPORT,93
5740 FOR I%=35 TO 128:OUT DATAPORT,PAR%(I%):NEXT I%:OUT DATAPORT,247
5745 OUT STATPORT, 255: OUT STATPORT,63: GOSUB 4955
5750 PRINT:FOR I%=112 TO 121:PRINT CHR$(PAR%(I%));:NEXT I%:PRINT
5755 GOSUB 4955: CLOSE#1: CNT=TRP:GOSUB 5765: RETURN
5760 :
5765 REM ...do "TX/DX permanent voice store"
5770 IF TXSEL=0 THEN  GOTO 5790
5775 BUTTON= 65: STATE=127:GOSUB 4815: BUTTON= 72: STATE=127:GOSUB 4815
5780 BUTTON= 65: STATE=0:GOSUB 4815
5785 BUTTON= 72: STATE=127:GOSUB 4815:GOTO 5800
5790 BUTTON= 114: STATE=127: GOSUB 4815: REM ..memstore for DX11
5795 BUTTON=CNT+75:GOSUB 4815:STATE=0:BUTTON=114:GOSUB 4815
5800 RETURN
5805 REM ...toggle TX81z/ Dx11 select
5810 IF TXSEL=1  THEN TXSEL = 0    ELSE TXSEL=1
5815 RETURN
5820 :
