10 REM SOUND GENERATION PROGRAM 20 REM N$ IS NAMES OF SOUNDS 30 REM D(X,Y) IS DATA VALUE X FOR SOUND Y 40 REM LR IS LINE NUMBER OF SOUND DATA ON DISPLAY 50 REM BS IS NUMBER OF BYTES INTO LINE OF DISPLAY FOR SHAPE BITS 60 REM BC IS NUMBER OF BYTES INTO LINE OF DISPLAY FOR CHANNEL BITS 70 REM RN$ IS REGISTER NAME 80 REM TH IS TONE REGISTER, LOW LIMIT 90 REM TL IS TONE REGISTER, LOW LIMIT 100 REM EH IS ENVELOPE PERIOD, HIGH LIMIT 110 REM EL IS ENVELOPE PERIOD, LOW LIMIT 120 REM NH IS NOISE FREQUENCY, HIGH LIMIT 130 REM NL IS NOISE FREQUENCY, LOW LIMIT 140 CLEAR 1000 150 GOSUB 43000 160 FAST 170 VINPUT 23*80,"PRESS 'RETURN' TO BEGIN EXECUTION";, LINE A$ 180 REM SET STARTING RANGES FOR VARIABLES 190 TH=30000:TL=30 200 EH=8:EL=.1 210 NH=31:NL=0 220 REM DEFINE DATA ADDRESSES 230 VA=PEEK(&105)+256*PEEK(&106):POKE VA+&7FF,12 240 PR=128:PD=129 250 DIM N$(19),D(9,19),RN$(13) 260 FILL 32:POKE VA+&7FF,12 270 CR$=CHR$(&7F) 280 RESTORE 290 REM LOAD LINE NUMBER ARRAY 300 FOR I=0 TO 9 310 READ LR(I) 320 NEXT 330 REM LOAD LINE ADDRESS MAP FOR SHAPE BITS 340 FOR I=0 TO 3 350 READ BS(I) 360 NEXT I 370 REM LOAD LINE ADDRESS MAP FOR CHANNEL ENABLE BITS 380 FOR I=0 TO 5 390 READ BC(I) 400 NEXT I 410 FOR I=0 TO 13 420 READ RN$(I) 430 NEXT I 440 DATA 6,7,8,11,14,15,16,19,20,23 450 DATA 17,27,40,48 460 DATA 17,22,27,40,45,50 470 DATA "R0 - CHANNEL A, FINE TUNE" 480 DATA "R1 - CHANNEL A, COARSE TUNE" 490 DATA "R2 - CHANNEL B, FINE TUNE" 500 DATA "R3 - CHANNEL B, COARSE TUNE" 510 DATA "R4 - CHANNEL C, FINE TUNE" 520 DATA "R5 - CHANNEL C, COARSE TUNE" 530 DATA "R6 - NOISE PERIOD" 540 DATA "R7 - ENABLE" 550 DATA "R10 - CHANNEL A, AMPLITUDE" 560 DATA "R11 - CHANNEL B, AMPLITUDE" 570 DATA "R12 - CHANNEL C, AMPLITUDE" 580 DATA "R13 - ENVELOPE, FINE TUNE" 590 DATA "R14 - ENVELOPE, COARSE TUNE" 600 DATA "R15 - ENVELOPE SHAPE" 1000 FILL 32:VPRINT 30,"MAIN MENU" 1010 VPRINT 240,"KEY FUNCTION" 1020 VPRINT 400," A - DEFINE NEW SOUND" 1030 VPRINT 480," B - MODIFY EXISTING SOUND" 1040 VPRINT 560," C - PLAYBACK SOUND" 1050 VPRINT 640," D - LIST ALL SOUNDS" 1060 VPRINT 720," E - EXPERIMENT" 1070 VPRINT 800," F - PRINT SOUND" 1080 VPRINT 880," G - CHANGE SOUND NAME" 1090 VPRINT 960," H - SAVE SOUND" 1100 VPRINT 1040," I - LOAD SAVED SOUND" 1110 VPRINT 1120," J - DISK DIRECTORY" 1120 VPRINT 1200," K - MODIFY LIMITS" 1130 VPRINT 1280," L - EXIT PROGRAM" 1140 IP=CINP(3) 1150 ON IP-64 GOTO 2000,3000,4000,5000,6000,7000,8000,9000,10000,11000,12000,13000 1160 GOTO 1140 2000 REM DEFINE NEW SOUND 2010 GOSUB 30000 2020 GOSUB 39000 2030 SN=RV 2040 IF N$(SN)="" THEN 2060 2050 VPRINT 119,"SOUND ALREADY EXISTS":GOTO 2020 2060 VPRINT 119,SPC(20) 2070 VINPUT 44,"SOUND NAME: ";,N$(SN) 2080 VPRINT 44,SPC(36) 2090 VPRINT 44,N$(SN) 2100 GOTO 3050 3000 REM MODIFY EXISTING SOUND 3010 GOSUB 30000 3020 GOSUB 39000 3030 SN=RV 3040 IF N$(SN)="" THEN VPRINT 119,"SOUND NOT ON FILE":GOTO 3020 3050 GOSUB 35000 3060 LI=0 3070 VPRINT LR(LI)*80,CR$ 3080 IP=CINP(3) 3090 IP$=CHR$(IP) 3100 IF IP$="M" THEN 1000:REM MAIN MENU 3110 IF IP$="D" THEN 3150:REM STEP DOWN 3120 IF IP$="U" THEN 3190:REM STEP UP 3130 IF IP$="V" THEN GOSUB 40000:REM VARY 3140 GOTO 3070 3150 IF LI>=9 THEN LI=9:GOTO 3080 3160 VPRINT LR(LI)*80," " 3170 LI=LI+1 3180 GOTO 3070 3190 IF LI<=0 THEN LI=0:GOTO 3080 3200 VPRINT LR(LI)*80," " 3210 LI=LI-1 3220 GOTO 3070 4000 REM PLAYBACK SOUND 4010 GOSUB 30000 4020 GOSUB 39000 4030 SN=RV 4040 IF N$(SN)="" THEN VPRINT 119,"SOUND NOT ON FILE":GOTO 4020 4050 GOSUB 35000:GOSUB 42000 4060 VPRINT 119,"PRESS ANY KEY TO RETURN TO MAIN MENU" 4070 IP=CINP(3):IP=0 4080 FOR I=0 TO 13 4090 OUT PR,I:OUT PD,0 4100 NEXT I 4110 GOTO 1000 5000 REM LIST ALL SOUNDS 5010 FILL 32 5020 VPRINT 80,"SOUND NUMBER NAME" 5030 FOR I=0 TO 19 5040 VPRINT 80*(I+3),I;TAB(18);N$(I) 5050 NEXT I 5060 VINPUT 23*80,"PRESS 'RETURN'";, LINE A$ 5070 GOTO 1000 6000 REM EXPERIMENT MODE 6010 GOSUB 30000 6020 GOSUB 39000 6030 SN=RV 6040 IF N$(SN)="" THEN VPRINT 119,"SOUND NOT ON FILE":GOTO 6020 6050 GOSUB 35000 6060 GOSUB 42000 6070 LI=0 6080 VPRINT LR(LI)*80,CR$ 6090 IP=CINP(3) 6100 IP$=CHR$(IP) 6110 IF IP$="M" THEN 4080:REM MAIN MENU 6120 IF IP$="D" THEN 6160:REM STEP DOWN 6130 IF IP$="U" THEN 6200:REM STEP UP 6140 IF IP$="V" THEN 6240:REM VARY 6150 GOTO 6090 6160 IF LI>=9 THEN LI=9:GOTO 6090 6170 VPRINT LR(LI)*80," " 6180 LI=LI+1 6190 GOTO 6080 6200 IF LI<=0 THEN LI=0:GOTO 6090 6210 VPRINT LR(LI)*80," " 6220 LI=LI-1 6230 GOTO 6080 6240 GOSUB 42000:GOSUB 41000:GOTO 6080 7000 REM PRINT A SOUND 7010 GOSUB 30000 7020 GOSUB 39000 7030 SN=RV 7040 IF N$(SN)="" THEN VPRINT 119,"SOUND NOT ON FILE":GOTO 7020 7050 GOSUB 35000 7060 LPRINT 7070 FOR I=0 TO 23 7080 FOR J=0 TO 78 7090 D=PEEK(VA+80*I+J) 7100 IF D>127 THEN D=64 7110 LPRINT CHR$(D); 7120 NEXT J 7130 LPRINT 7140 NEXT I 7150 LPRINT :LPRINT 7160 LPRINT "REGISTER NAME";TAB(40);"PORT";TAB(50);"VALUE":LPRINT 7170 F=D(0,SN):GOSUB 36000 7180 LPRINT RN$(0);TAB(42);"0";TAB(51);FT 7190 LPRINT RN$(1);TAB(42);"1";TAB(51);CT 7200 F=D(1,SN):GOSUB 36000 7210 LPRINT RN$(2);TAB(42);"2";TAB(51);FT 7220 LPRINT RN$(3),TAB(42);"3";TAB(51);CT 7230 F=D(2,SN):GOSUB 36000 7240 LPRINT RN$(4);TAB(42);"4";TAB(51);FT 7250 LPRINT RN$(5);TAB(42);"5";TAB(51);CT 7260 F=D(3,SN):GOSUB 37000 7270 LPRINT RN$(6);TAB(42);"6";TAB(51);NP 7280 LPRINT RN$(7);TAB(42);"7";TAB(51);63-D(9,SN) 7290 LPRINT RN$(8);TAB(42);"8";TAB(51);D(4,SN) 7300 LPRINT RN$(9);TAB(42);"9";TAB(51);D(5,SN) 7310 LPRINT RN$(10);TAB(41);"10";TAB(51);D(6,SN) 7320 F=D(7,SN):GOSUB 38000 7330 LPRINT RN$(11);TAB(41);"11";TAB(51);FT 7340 LPRINT RN$(12);TAB(41);"12";TAB(51);CT 7350 LPRINT RN$(13);TAB(41);"13";TAB(51);D(8,SN) 7360 LPRINT :LPRINT :LPRINT 7370 GOTO 1000 8000 REM CHANGE SOUND NAME 8010 GOSUB 30000 8020 GOSUB 39000 8030 SN=RV 8040 IF N$(SN)="" THEN VPRINT 119,"SOUND NOT ON FILE":GOTO 8020 8050 GOSUB 35000 8060 VINPUT 40,"NEW SOUND NAME"; LINE N$(SN) 8070 GOTO 1000 9000 REM SAVE SOUND ON DISK 9010 GOSUB 30000 9020 GOSUB 39000 9030 SN=RV 9040 IF N$(SN)="" THEN VPRINT 119,"SOUND NOT ON FILE":GOTO 9020 9050 GOSUB 35000 9060 VINPUT 40,"FILE NAME"; LINE FI$ 9070 CREATE 0;FI$ 9080 DPRINT 0;N$(SN) 9090 FOR I=0 TO 9 9100 DPRINT 0;D(I,SN) 9110 NEXT I 9120 CLOSE 0 9130 GOTO 1000 10000 REM LOAD SAVED SOUND 10010 GOSUB 30000 10020 GOSUB 39000 10030 SN=RV 10040 IF ( NOT (N$(SN)="")) THEN VPRINT 119,"SOUND ALREADY EXISTS":GOTO 10020 10050 VINPUT 40,"FILE NAME"; LINE FI$ 10060 OPEN 0;FI$ 10070 DINPUT 0; LINE N$(SN) 10080 FOR I=0 TO 9 10090 DINPUT 0;D(I,SN) 10100 NEXT I 10110 CLOSE 0 10120 GOTO 1000 11000 REM PRINT DISK DIRECTORY 11010 FILL 32:PRINT 11020 DIR 11030 VINPUT 23*80,"PRESS 'RETURN'";, LINE A$ 11040 GOTO 1000 12000 REM MODIFY VARIABLE LIMITS 12010 FILL 32:PRINT 12020 INPUT "TONE HIGH LIMIT (30-125000)";IP:IF IP<>0 THEN TH=IP 12030 IF TH<30 THEN PRINT "TOO LOW":GOTO 12020 12040 IF TH>125000 THEN PRINT "TOO HIGH":GOTO 12020 12050 INPUT "TONE LOW LIMIT (30-125000)";IP:IF IP<>0 THEN TL=IP 12060 IF TL<30 THEN PRINT "TOO LOW":GOTO 12050 12070 IF TL>TH THEN PRINT "TOO HIGH":GOTO 12050 12080 INPUT "ENVELOPE HIGH LIMIT (.0001-8)";IP:IF IP<>0 THEN EH=IP 12090 IF EH<.0001 THEN PRINT "TOO LOW":GOTO 12080 12100 IF EH>8 THEN PRINT "TOO HIGH":GOTO 12080 12110 INPUT "ENVELOPE LOW LIMIT (.0001-8)";IP:IF IP<>0 THEN EL=IP 12120 IF EL<.0001 THEN PRINT "TOO LOW":GOTO 12110 12130 IF EL>EH THEN PRINT "TOO HIGH":GOTO 12110 12140 INPUT "NOISE HIGH LIMIT (0-31)";IP:IF IP<>0 THEN NH=IP 12150 IF NH<0 THEN PRINT "TOO LOW":GOTO 12140 12160 IF NH>31 THEN PRINT "TOO HIGH"; GOTO 12140 12170 INPUT "NOISE LOW LIMIT (0-31)";IP:IF IP<>0 THEN NL=IP 12180 IF NL<0 THEN PRINT "TOO LOW"; GOTO 12170 12190 IF NL>NH THEN PRINT "TOO HIGH":GOTO 12170 12200 GOTO 1000 13000 REM EXIT PROGRAM 13010 END 30000 REM CONTROL DISPLAY 30010 FILL 32 30020 VPRINT 0,"V=VARY, RETURN=LATCH" 30030 VPRINT 40,"SOUND:" 30040 VPRINT 80,"U=STEP UP" 30050 VPRINT 160,"D=STEP DOWN" 30060 VPRINT 240,"M=MAIN MENU" 30070 VPRINT 400,"TONES:";TL;TH; 30080 VPRINT 481,"A-" 30090 VPRINT 561,"B-" 30100 VPRINT 641,"C-" 30110 VPRINT 800,"NOISE:";NL;NH 30120 VPRINT 1040,"AMPLITUDE: (0-15)" 30130 VPRINT 1121,"A-" 30140 VPRINT 1201,"B-" 30150 VPRINT 1281,"C-" 30160 VPRINT 1440,"ENVELOPE:";EL;EH 30170 VPRINT 1601,"SHAPE: CONTINUE= ATTACK= ALTERNATE= HOLD=" 30180 VPRINT 1760,"CHANNEL ENABLE:" 30190 VPRINT 1848,"NOISE: C= B= A= TONE: C= B= A=" 30200 RETURN 31000 REM READ SWITCH BOX 31010 REM JS=PSEUDO JOYSTICK POSITION 31020 REM RL=LOWEST VALUE IN RANGE 31030 REM RH=HIGHEST VALUE IN RANGE 31040 REM RETURN RV=VALUE IN DEFINED RANGE 31050 REM ACCEPT "<" OR "," FOR DECREASE 31060 REM ACCEPT ">" OR "." FOR INCREASE 31070 REM ACCEPT 1-9 FOR SET POSITION 31080 REM ACCEPT RETURN AS TERMINATOR 31090 RI=CINP(3) 31100 IP=RI 31110 IF RI=13 THEN 31160 31120 IF RI>&39 OR RI<&31 THEN 31140 31130 JS=(RI-&30)*20:GOTO 31180 31140 IF RI=&3C OR RI=&2C THEN JS=JS-1 31150 IF RI=&3E OR RI=&2E THEN JS=JS+1 31160 IF JS<0 THEN JS=0 31170 IF JS>199 THEN JS=199 31180 RV=JS*((RH-RL)/199)+RL 31190 RETURN 32000 REM PLOT LINE FOR DISPLAY OF VALUE 32010 REM RL=LOW LIMIT, RH=HIGH LIMIT 32020 REM RV=ACTUAL VALUE, LN=LINE NUMBER 32030 IF RV>RH THEN RV=RH 32040 IF RV4095 THEN TP=4095 36040 CT=INT(TP/256) 36050 FT=INT(TP-256*CT) 36060 RETURN 37000 REM COMPUTE REGISTER VALUES FOR NOISE FREQUENCY 37010 NP=F 37020 RETURN 38000 REM COMPUTE REGISTER VALUES FOR ENVELOPE PERIOD 38010 IF F=0 THEN CT=0:FT=0:RETURN 38020 F=1/F 38030 EP=(2000000/F)/256 38040 CT=INT(EP/256) 38050 FT=INT(EP-256*CT) 38060 RETURN 39000 REM INPUT SCREEN SELECTION 39010 VINPUT 40,"(ENTER SOUND NUMBER) ";,RV 39020 VPRINT 40,SPC(40) 39030 RV=ABS(INT(RV)):IF RV>19 THEN 39010 39040 VPRINT 40,RV 39050 VPRINT 44,N$(RV) 39060 RETURN 40000 REM VARY SELECTED INPUT ON LINE LN 40010 VPRINT LR(LI)*80,">" 40020 LN=LR(LI):IP=0 40030 IF LI<3 THEN RL=TL:RH=TH 40040 IF LI=3 THEN RL=NL:RH=NH 40050 IF LI>3 AND LI<7 THEN RL=0:RH=16 40060 IF LI=7 THEN RL=EL:RH=EH 40070 IF LI=8 THEN RL=0:RH=3:BT=0 40080 IF LI=9 THEN RL=0:RH=5:BT=0 40090 IF LI<8 THEN JS=(D(LI,SN)-RL)/((RH-RL)/199) ELSE JS=0 40100 IF IP=13 THEN RETURN 40110 ON LI GOTO 40120,40120,40120,40140,40140,40140,40170,40180,40300 40120 GOSUB 31000:RV=INT(RV) 40130 GOSUB 32000:D(LI,SN)=RV:GOTO 40100 40140 GOSUB 31000:RV=INT(RV+.5):IF RV<>16 THEN GOTO 40130 40150 VPRINT LN*80+4,"ENVELOPE";SPC(68) 40160 D(LI,SN)=RV:GOTO 40100 40170 GOSUB 31000:GOTO 40130 40180 GOSUB 31000 40190 VPRINT 20*80+BS(3-BT)+1," " 40200 BT=3-INT(RV+.5) 40210 VPRINT 20*80+BS(3-BT)+1,CR$ 40220 IF IP<>13 THEN 40180 40230 VPRINT 20*80+BS(3-BT)+1," " 40240 DV=INT(2^BT) 40250 IF (D(8,SN) AND DV) THEN 40280 40260 D(8,SN)=D(8,SN)+DV 40270 RV=D(8,SN):GOSUB 33000:RETURN 40280 D(8,SN)=D(8,SN)-DV 40290 GOTO 40270 40300 GOSUB 31000 40310 VPRINT 23*80+BC(5-BT)+1," " 40320 BT=5-INT(RV+.5) 40330 VPRINT 23*80+BC(5-BT)+1,"<" 40340 IF IP<>13 THEN 40300 40350 VPRINT 23*80+BC(5-BT)+1," " 40360 DV=INT(2^BT) 40370 IF (D(9,SN) AND DV) THEN 40400 40380 D(9,SN)=D(9,SN)+DV 40390 RV=D(9,SN):GOSUB 34000:RETURN 40400 D(9,SN)=D(9,SN)-DV 40410 GOTO 40390 41000 REM DYNAMICALLY VARY SELECTED INPUT ON LINE LN 41010 VPRINT LR(LI)*80,">" 41020 LN=LR(LI):IP=0 41030 IF LI<3 THEN RL=TL:RH=TH 41040 IF LI=3 THEN RL=NL:RH=NH 41050 IF LI>3 AND LI<7 THEN RL=0:RH=16 41060 IF LI=7 THEN RL=EL:RH=EH 41070 IF LI=8 THEN RL=0:RH=3:BT=0 41080 IF LI=9 THEN RL=0:RH=5:BT=0 41090 IF LI<8 THEN JS=(D(LI,SN)-RL)/((RH-RL)/199) ELSE JS=0 41100 IF IP=13 THEN RETURN 41110 ON LI GOTO 41120,41120,41170,41240,41240,41240,41270,41330,41450 41120 GOSUB 31000:RV=INT(RV):GOSUB 32000 41130 D(LI,SN)=RV:F=RV:GOSUB 36000 41140 OUT PR,LI*2:OUT PD,FT 41150 OUT PR,LI*2+1:OUT PD,CT 41160 GOTO 41100 41170 GOSUB 31000 41180 RV=INT(RV) 41190 GOSUB 32000 41200 F=RV 41210 GOSUB 37000:D(3,SN)=F 41220 OUT PR,6:OUT PD,NP 41230 GOTO 41100 41240 GOSUB 31000:RV=INT(RV+.5):OUT PR,LI+4:OUT PD,RV:D(LI,SN)=RV:IF RV<>16 THEN GOSUB 32000:GOTO 41100 41250 VPRINT LN*80+4,"ENVELOPE";SPC(68) 41260 GOTO 41100 41270 GOSUB 31000:GOSUB 32000 41280 D(LI,SN)=RV 41290 F=RV:GOSUB 38000 41300 OUT PR,11:OUT PD,FT 41310 OUT PR,12:OUT PD,CT 41320 GOTO 41100 41330 GOSUB 31000 41340 VPRINT 20*80+BS(3-BT)+1," " 41350 BT=3-INT(RV+.5) 41360 VPRINT 20*80+BS(3-BT)+1,"<" 41370 IF IP<>13 THEN 41330 41380 VPRINT 20*80+BS(3-BT)+1," " 41390 DV=INT(2^BT) 41400 IF (D(8,SN) AND DV) THEN 41430 41410 D(8,SN)=D(8,SN)+DV 41420 RV=D(8,SN):GOSUB 33000:OUT PR,13:OUT PD,RV:RETURN 41430 D(8,SN)=D(8,SN)-DV 41440 GOTO 41420 41450 GOSUB 31000 41460 VPRINT 23*80+BC(5-BT)+1," " 41470 BT=5-INT(RV+.5) 41480 VPRINT 23*80+BC(5-BT)+1,"<" 41490 IF IP<>13 THEN 41450 41500 VPRINT 23*80+BC(5-BT)+1," " 41510 DV=INT(2^BT) 41520 IF (D(9,SN) AND DV) THEN 41550 41530 D(9,SN)=D(9,SN)+DV 41540 RV=D(9,SN):GOSUB 34000:OUT PR,7:OUT PD,255-RV:RETURN 41550 D(9,SN)=D(9,SN)-DV 41560 GOTO 41540 42000 REM WRITE CURRENT SOUND TO CONTROL PORTS 42010 FOR I=0 TO 13 42020 OUT PR,I:OUT PD,0 42030 NEXT I 42040 F=D(0,SN):GOSUB 36000 42050 OUT PR,0:OUT PD,FT 42060 OUT PR,1:OUT PD,CT 42070 F=D(1,SN):GOSUB 36000 42080 OUT PR,2:OUT PD,FT 42090 OUT PR,3:OUT PD,CT 42100 F=D(2,SN):GOSUB 36000 42110 OUT PR,4:OUT PD,FT 42120 OUT PR,5:OUT PD,CT 42130 F=D(3,SN):GOSUB 37000 42140 OUT PR,6:OUT PD,NP 42150 OUT PR,7:OUT PD,255-D(9,SN) 42160 OUT PR,8:OUT PD,D(4,SN) 42170 OUT PR,9:OUT PD,D(5,SN) 42180 OUT PR,10:OUT PD,D(6,SN) 42190 F=D(7,SN):GOSUB 38000 42200 OUT PR,11:OUT PD,FT 42210 OUT PR,12:OUT PD,CT 42220 OUT PR,13:OUT PD,D(8,SN) 42230 RETURN 43000 REM PRINT INSTRUCTIONS 43010 FILL 32 43020 RESTORE 43080 43030 FOR I=0 TO 20 43040 READ A$ 43050 VPRINT I*80,A$ 43060 NEXT 43070 RETURN 43080 DATA " *** HAWKEYE GRAFIX SOUND GENERATION PROGRAM ***" 43090 DATA "" 43100 DATA " This program is designed for use in the development of sound effects with the" 43110 DATA "General Instruments AY-3-8910/8912 sound generator chips, addressed at port" 43120 DATA "128 for register select, and 129 for data." 43130 DATA "" 43140 DATA " In the menu mode, press the key indicated to execute the function desired." 43150 DATA "" 43160 DATA " In the define, modify, or experiment modes, the keys operate in the following" 43170 DATA "manner:" 43180 DATA "" 43190 DATA " Pressing the 'U' key will move the selection cursor up." 43200 DATA " Pressing the 'D' key will move the selection cursor down." 43210 DATA " Pressing the 'M' key will return to the main